Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
mikf
GitHub Repository: mikf/gallery-dl
Path: blob/master/gallery_dl/extractor/cien.py
5399 views
1
# -*- coding: utf-8 -*-
2
3
# Copyright 2024-2025 Mike Fährmann
4
#
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License version 2 as
7
# published by the Free Software Foundation.
8
9
"""Extractors for https://ci-en.net/"""
10
11
from .common import Extractor, Message
12
from .. import text
13
14
BASE_PATTERN = r"(?:https?://)?ci-en\.(?:net|dlsite\.com)"
15
16
17
class CienExtractor(Extractor):
18
category = "cien"
19
root = "https://ci-en.net"
20
request_interval = (1.0, 2.0)
21
22
def __init__(self, match):
23
self.root = text.root_from_url(match[0])
24
Extractor.__init__(self, match)
25
26
def _init(self):
27
self.cookies.set("accepted_rating", "r18g", domain="ci-en.dlsite.com")
28
29
def _pagination_articles(self, url, params):
30
data = {"_extractor": CienArticleExtractor}
31
params["page"] = text.parse_int(params.get("page"), 1)
32
33
while True:
34
page = self.request(url, params=params).text
35
36
for card in text.extract_iter(
37
page, ' class="c-cardCase-item', '</div>'):
38
article_url = text.extr(card, ' href="', '"')
39
yield Message.Queue, article_url, data
40
41
if ' rel="next"' not in page:
42
return
43
params["page"] += 1
44
45
46
class CienArticleExtractor(CienExtractor):
47
subcategory = "article"
48
filename_fmt = "{num:>02} {filename}.{extension}"
49
directory_fmt = ("{category}", "{author[name]}", "{post_id} {name}")
50
archive_fmt = "{post_id}_{num}"
51
pattern = BASE_PATTERN + r"/creator/(\d+)/article/(\d+)"
52
example = "https://ci-en.net/creator/123/article/12345"
53
54
def items(self):
55
author_id, post_id = self.groups
56
url = f"{self.root}/creator/{author_id}/article/{post_id}"
57
page = self.request(url, notfound="article").text
58
59
files = self._extract_files(page)
60
post = self._extract_jsonld(page)[0]
61
post["post_url"] = url
62
post["post_id"] = text.parse_int(post_id)
63
post["count"] = len(files)
64
post["date"] = text.parse_datetime(post["datePublished"])
65
66
try:
67
post["author"]["id"] = text.parse_int(author_id)
68
del post["publisher"]
69
del post["sameAs"]
70
except Exception:
71
pass
72
73
yield Message.Directory, post
74
for post["num"], file in enumerate(files, 1):
75
post.update(file)
76
if "extension" not in file:
77
text.nameext_from_url(file["url"], post)
78
yield Message.Url, file["url"], post
79
80
def _extract_files(self, page):
81
files = []
82
83
filetypes = self.config("files")
84
if filetypes is None:
85
self._extract_files_image(page, files)
86
self._extract_files_video(page, files)
87
self._extract_files_download(page, files)
88
self._extract_files_gallery(page, files)
89
else:
90
generators = {
91
"image" : self._extract_files_image,
92
"video" : self._extract_files_video,
93
"download": self._extract_files_download,
94
"gallery" : self._extract_files_gallery,
95
"gallerie": self._extract_files_gallery,
96
}
97
if isinstance(filetypes, str):
98
filetypes = filetypes.split(",")
99
for ft in filetypes:
100
generators[ft.rstrip("s")](page, files)
101
102
return files
103
104
def _extract_files_image(self, page, files):
105
for image in text.extract_iter(
106
page, 'class="file-player-image"', "</figure>"):
107
size = text.extr(image, ' data-size="', '"')
108
w, _, h = size.partition("x")
109
110
files.append({
111
"url" : text.extr(image, ' data-raw="', '"'),
112
"width" : text.parse_int(w),
113
"height": text.parse_int(h),
114
"type" : "image",
115
})
116
117
def _extract_files_video(self, page, files):
118
for video in text.extract_iter(
119
page, "<vue-file-player", "</vue-file-player>"):
120
path = text.extr(video, ' base-path="', '"')
121
name = text.extr(video, ' file-name="', '"')
122
auth = text.extr(video, ' auth-key="', '"')
123
124
file = text.nameext_from_url(name)
125
file["url"] = f"{path}video-web.mp4?{auth}"
126
file["type"] = "video"
127
files.append(file)
128
129
def _extract_files_download(self, page, files):
130
for download in text.extract_iter(
131
page, 'class="downloadBlock', "</div>"):
132
name = text.extr(download, "<p>", "<")
133
134
file = text.nameext_from_url(name.rpartition(" ")[0])
135
file["url"] = text.extr(download, ' href="', '"')
136
file["type"] = "download"
137
files.append(file)
138
139
def _extract_files_gallery(self, page, files):
140
for gallery in text.extract_iter(
141
page, "<vue-image-gallery", "</vue-image-gallery>"):
142
143
url = self.root + "/api/creator/gallery/images"
144
params = {
145
"hash" : text.extr(gallery, ' hash="', '"'),
146
"gallery_id": text.extr(gallery, ' gallery-id="', '"'),
147
"time" : text.extr(gallery, ' time="', '"'),
148
}
149
data = self.request_json(url, params=params)
150
url = self.root + "/api/creator/gallery/imagePath"
151
152
for params["page"], params["file_id"] in enumerate(
153
data["imgList"]):
154
path = self.request_json(url, params=params)["path"]
155
156
file = params.copy()
157
file["url"] = path
158
files.append(file)
159
160
161
class CienCreatorExtractor(CienExtractor):
162
subcategory = "creator"
163
pattern = BASE_PATTERN + r"/creator/(\d+)(?:/article(?:\?([^#]+))?)?/?$"
164
example = "https://ci-en.net/creator/123"
165
166
def items(self):
167
url = f"{self.root}/creator/{self.groups[0]}/article"
168
params = text.parse_query(self.groups[1])
169
params["mode"] = "list"
170
return self._pagination_articles(url, params)
171
172
173
class CienRecentExtractor(CienExtractor):
174
subcategory = "recent"
175
pattern = BASE_PATTERN + r"/mypage/recent(?:\?([^#]+))?"
176
example = "https://ci-en.net/mypage/recent"
177
178
def items(self):
179
url = self.root + "/mypage/recent"
180
params = text.parse_query(self.groups[0])
181
return self._pagination_articles(url, params)
182
183
184
class CienFollowingExtractor(CienExtractor):
185
subcategory = "following"
186
pattern = BASE_PATTERN + r"/mypage/subscription(/following)?"
187
example = "https://ci-en.net/mypage/subscription"
188
189
def items(self):
190
url = self.root + "/mypage/subscription" + (self.groups[0] or "")
191
page = self.request(url).text
192
data = {"_extractor": CienCreatorExtractor}
193
194
for subscription in text.extract_iter(
195
page, 'class="c-grid-subscriptionInfo', '</figure>'):
196
url = text.extr(subscription, ' href="', '"')
197
yield Message.Queue, url, data
198
199