1
0
mirror of https://github.com/mikf/gallery-dl.git synced 2024-11-23 11:12:40 +01:00
gallery-dl/gallery_dl/extractor/seiga.py

200 lines
7.1 KiB
Python
Raw Normal View History

2016-08-09 16:36:30 +02:00
# -*- coding: utf-8 -*-
2019-01-30 16:18:22 +01:00
# Copyright 2016-2019 Mike Fährmann
2016-08-09 16:36:30 +02:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
2019-02-21 22:51:11 +01:00
"""Extract images from https://seiga.nicovideo.jp/"""
2016-08-09 16:36:30 +02:00
from .common import Extractor, Message
from .. import text, util, exception
2016-08-09 16:36:30 +02:00
from ..cache import cache
2017-02-01 00:53:19 +01:00
2017-01-04 14:20:37 +01:00
class SeigaExtractor(Extractor):
"""Base class for seiga extractors"""
2016-08-09 16:36:30 +02:00
category = "seiga"
archive_fmt = "{image_id}"
cookiedomain = ".nicovideo.jp"
2019-02-21 22:51:11 +01:00
root = "https://seiga.nicovideo.jp"
2016-08-09 16:36:30 +02:00
def __init__(self, match):
Extractor.__init__(self, match)
2017-12-03 01:38:24 +01:00
self.start_image = 0
2016-08-09 16:36:30 +02:00
def items(self):
2017-01-04 14:20:37 +01:00
self.login()
images = iter(self.get_images())
data = next(images)
2016-08-09 16:36:30 +02:00
yield Message.Version, 1
yield Message.Directory, data
2017-12-03 01:38:24 +01:00
for image in util.advance(images, self.start_image):
2017-01-04 14:20:37 +01:00
data.update(image)
data["extension"] = None
yield Message.Url, self.get_image_url(data["image_id"]), data
2017-01-04 14:20:37 +01:00
def get_images(self):
"""Return iterable containing metadata and images"""
2016-08-09 16:36:30 +02:00
def get_image_url(self, image_id):
"""Get url for an image with id 'image_id'"""
2019-02-21 22:51:11 +01:00
url = "{}/image/source/{}".format(self.root, image_id)
response = self.request(
url, method="HEAD", allow_redirects=False, notfound="image")
2016-08-09 16:36:30 +02:00
return response.headers["Location"].replace("/o/", "/priv/", 1)
2017-01-04 14:20:37 +01:00
def login(self):
"""Login and set necessary cookies"""
2017-07-25 14:59:41 +02:00
if not self._check_cookies(("user_session",)):
username, password = self._get_auth_info()
2019-01-30 17:09:32 +01:00
self._update_cookies(self._login_impl(username, password))
2017-01-04 14:20:37 +01:00
2019-03-14 22:21:49 +01:00
@cache(maxage=7*24*3600, keyarg=1)
2017-01-04 14:20:37 +01:00
def _login_impl(self, username, password):
2017-03-17 09:42:59 +01:00
self.log.info("Logging in as %s", username)
2016-08-09 16:36:30 +02:00
url = "https://account.nicovideo.jp/api/v1/login"
data = {"mail_tel": username, "password": password}
2019-01-30 17:09:32 +01:00
self.request(url, method="POST", data=data)
2016-08-09 16:36:30 +02:00
if "user_session" not in self.session.cookies:
raise exception.AuthenticationError()
del self.session.cookies["nicosid"]
return self.session.cookies
2017-01-04 14:20:37 +01:00
class SeigaUserExtractor(SeigaExtractor):
"""Extractor for images of a user from seiga.nicovideo.jp"""
subcategory = "user"
directory_fmt = ("{category}", "{user[id]}")
filename_fmt = "{category}_{user[id]}_{image_id}.{extension}"
pattern = (r"(?:https?://)?(?:www\.|(?:sp\.)?seiga\.)?nicovideo\.jp/"
r"user/illust/(\d+)(?:\?(?:[^&]+&)*sort=([^&#]+))?")
test = (
2019-02-21 22:51:11 +01:00
("https://seiga.nicovideo.jp/user/illust/39537793", {
"pattern": r"https://lohas\.nicoseiga\.jp/priv/[0-9a-f]+/\d+/\d+",
2018-03-08 18:04:34 +01:00
"count": ">= 4",
2017-12-30 19:19:36 +01:00
"keyword": {
"user": {
"id": 39537793,
"message": str,
"name": str,
2017-12-30 19:19:36 +01:00
},
"clips": int,
"comments": int,
"count": int,
"extension": None,
"image_id": int,
"title": str,
"views": int,
},
2017-01-04 14:20:37 +01:00
}),
2019-02-21 22:51:11 +01:00
("https://seiga.nicovideo.jp/user/illust/79433", {
"exception": exception.NotFoundError,
2017-01-04 14:20:37 +01:00
}),
2019-02-21 22:51:11 +01:00
("https://seiga.nicovideo.jp/user/illust/39537793"
"?sort=image_view&target=illust_all"),
("https://sp.seiga.nicovideo.jp/user/illust/39537793"),
)
2017-01-04 14:20:37 +01:00
def __init__(self, match):
SeigaExtractor.__init__(self, match)
self.user_id, self.order = match.groups()
2017-12-03 01:38:24 +01:00
self.start_page = 1
def skip(self, num):
pages, images = divmod(num, 40)
2017-12-03 01:38:24 +01:00
self.start_page += pages
self.start_image += images
return num
def get_metadata(self, page):
"""Collect metadata from 'page'"""
data = text.extract_all(page, (
("name" , '<img alt="', '"'),
("msg" , '<li class="user_message">', '</li>'),
(None , '<span class="target_name">すべて</span>', ''),
("count", '<span class="count ">', '</span>'),
))[0]
if not data["name"] and "ユーザー情報が取得出来ませんでした" in page:
raise exception.NotFoundError("user")
return {
"user": {
"id": text.parse_int(self.user_id),
"name": data["name"],
"message": (data["msg"] or "").strip(),
},
"count": text.parse_int(data["count"]),
}
2017-01-04 14:20:37 +01:00
def get_images(self):
2019-02-21 22:51:11 +01:00
url = "{}/user/illust/{}".format(self.root, self.user_id)
2017-12-03 01:38:24 +01:00
params = {"sort": self.order, "page": self.start_page,
"target": "illust_all"}
while True:
cnt = 0
page = self.request(url, params=params).text
2017-12-03 01:38:24 +01:00
if params["page"] == self.start_page:
yield self.get_metadata(page)
for info in text.extract_iter(
page, '<li class="list_item', '</a></li> '):
data = text.extract_all(info, (
("image_id", '/seiga/im', '"'),
("title" , '<li class="title">', '</li>'),
("views" , '</span>', '</li>'),
("comments", '</span>', '</li>'),
("clips" , '</span>', '</li>'),
))[0]
for key in ("image_id", "views", "comments", "clips"):
data[key] = text.parse_int(data[key])
yield data
cnt += 1
if cnt < 40:
return
params["page"] += 1
2017-01-04 14:20:37 +01:00
class SeigaImageExtractor(SeigaExtractor):
"""Extractor for single images from seiga.nicovideo.jp"""
subcategory = "image"
filename_fmt = "{category}_{image_id}.{extension}"
pattern = (r"(?:https?://)?(?:"
r"(?:seiga\.|www\.)?nicovideo\.jp/(?:seiga/im|image/source/)"
r"|sp\.seiga\.nicovideo\.jp/seiga/#!/im"
r"|lohas\.nicoseiga\.jp/(?:thumb|(?:priv|o)/[^/]+/\d+)/)(\d+)")
test = (
2019-02-21 22:51:11 +01:00
("https://seiga.nicovideo.jp/seiga/im5977527", {
"keyword": "f66ba5de33d4ce2cb57f23bb37e1e847e0771c10",
2017-01-04 14:20:37 +01:00
"content": "d9202292012178374d57fb0126f6124387265297",
}),
2019-02-21 22:51:11 +01:00
("https://seiga.nicovideo.jp/seiga/im123", {
2017-01-04 14:20:37 +01:00
"exception": exception.NotFoundError,
}),
2019-02-21 22:51:11 +01:00
("https://seiga.nicovideo.jp/image/source/5977527"),
("https://sp.seiga.nicovideo.jp/seiga/#!/im5977527"),
("https://lohas.nicoseiga.jp/thumb/5977527i"),
("https://lohas.nicoseiga.jp/priv"
"/759a4ef1c639106ba4d665ee6333832e647d0e4e/1549727594/5977527"),
("https://lohas.nicoseiga.jp/o"
"/759a4ef1c639106ba4d665ee6333832e647d0e4e/1549727594/5977527"),
)
2017-01-04 14:20:37 +01:00
def __init__(self, match):
SeigaExtractor.__init__(self, match)
2017-01-04 14:20:37 +01:00
self.image_id = match.group(1)
def skip(self, num):
2017-12-03 01:38:24 +01:00
self.start_image += num
return num
2017-01-04 14:20:37 +01:00
def get_images(self):
return ({}, {"image_id": text.parse_int(self.image_id)})