fix dlsite-maniax

This commit is contained in:
Nebel 2024-06-30 23:40:04 +09:00
parent 27c4784793
commit 3dfe483973
Signed by: nebel
GPG key ID: 79807D08C6EF6460
5 changed files with 92 additions and 23 deletions

View file

@ -10,7 +10,7 @@ $ npx https://git.fogtype.com/nebel/gadl/archive/main.tar.gz --help
- Google Play ブックス (漫画) - Google Play ブックス (漫画)
- DMM ブックス (漫画) - DMM ブックス (漫画)
- DLsite 同人 - DLsite 同人/がるまに/成年コミック
- FANZA 同人 - FANZA 同人
## License ## License

View file

@ -1,8 +1,10 @@
import * as Playwright from "playwright"; import type * as Playwright from "playwright";
import { chromium, devices } from "playwright"; import { chromium, devices } from "playwright";
import type { Database } from "./database"; import type { Database } from "./database";
import type { TPlatform } from "./platform"; import type { TPlatform } from "./platform";
export type PageOrFrame = Playwright.Page | Playwright.Frame;
export type ImageFile = { export type ImageFile = {
url: string; url: string;
blocks?: Array<Record<string, number>>; blocks?: Array<Record<string, number>>;

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "@fogtype/gadl", "name": "@fogtype/gadl",
"version": "1.5.0", "version": "1.5.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@fogtype/gadl", "name": "@fogtype/gadl",
"version": "1.5.0", "version": "1.5.1",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
"fflate": "^0.8.1", "fflate": "^0.8.1",

View file

@ -1,6 +1,6 @@
{ {
"name": "@fogtype/gadl", "name": "@fogtype/gadl",
"version": "1.5.0", "version": "1.5.1",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"type": "module", "type": "module",
"bin": "bin/run.js", "bin": "bin/run.js",

View file

@ -1,5 +1,41 @@
import type {
Browser,
BrowserContext,
ImageFile,
PageOrFrame,
} from "../browser";
import type { Book } from "../library"; import type { Book } from "../library";
import type { Browser, BrowserContext, ImageFile } from "../browser";
// リーダーのページ要素
const workTreeItemsSelector = `[class^=_worktree_] li[class^=_item_]`;
function Reader(page: PageOrFrame, readerUrl: string) {
const workId = /^https:[/][/]play[.]dlsite[.]com[/]#[/]work[/]([^/]+)/.exec(
readerUrl,
)?.[1];
if (!workId) {
throw new Error(`workId is not included: ${readerUrl}`);
}
return {
async load() {
await page.goto(readerUrl);
},
async downloadUrl(): Promise<null | string> {
const isBook = workId.startsWith("B");
if (isBook) {
// PDFファイルでないことを確認
const items = await page.waitForSelector(workTreeItemsSelector);
const text = await items.textContent();
if (!text?.match(/PDF/u)) return null;
}
return `https://www.dlsite.com/home/download/=/product_id/${workId}.html`;
},
};
}
export function DlsiteManiax(browser: Browser) { export function DlsiteManiax(browser: Browser) {
async function* getAllBooks(ctx: BrowserContext): AsyncGenerator<Book> { async function* getAllBooks(ctx: BrowserContext): AsyncGenerator<Book> {
@ -37,6 +73,7 @@ export function DlsiteManiax(browser: Browser) {
ja_JP: string; ja_JP: string;
}; };
}; };
author_name: string | null;
}>; }>;
} = await res.json(); } = await res.json();
@ -46,7 +83,7 @@ export function DlsiteManiax(browser: Browser) {
platform: "dlsite-maniax", platform: "dlsite-maniax",
readerUrl: `https://play.dlsite.com/#/work/${work.workno}`, readerUrl: `https://play.dlsite.com/#/work/${work.workno}`,
title: work.name.ja_JP || "", title: work.name.ja_JP || "",
authors: [work.maker.name.ja_JP || ""], authors: [work.author_name || work.maker.name.ja_JP || ""],
}; };
process.stderr.write("."); process.stderr.write(".");
@ -69,20 +106,13 @@ export function DlsiteManiax(browser: Browser) {
async getFiles(book: Book): Promise<Array<() => Promise<Blob>>> { async getFiles(book: Book): Promise<Array<() => Promise<Blob>>> {
const ctx = await browser.loadBrowserContext("dlsite-maniax"); const ctx = await browser.loadBrowserContext("dlsite-maniax");
const page = await ctx.newPage(); const page = await ctx.newPage();
const reader = Reader(page, book.readerUrl);
await page.goto(book.readerUrl); await reader.load();
const downloadUrl = await reader.downloadUrl();
const [, workId] = if (downloadUrl) {
/^https:[/][/]play[.]dlsite[.]com[/]#[/]work[/]([^/]+)/.exec( const imageFile: ImageFile = { url: downloadUrl };
book.readerUrl,
) ?? [];
if (!workId) {
throw new Error(`workId is not included: ${book.readerUrl}`);
}
const url = `https://www.dlsite.com/home/download/=/product_id/${workId}.html`;
const imageFile = { url };
return [ return [
async () => { async () => {
@ -93,6 +123,43 @@ export function DlsiteManiax(browser: Browser) {
return blob; return blob;
}, },
]; ];
}
// ページ数 … 画面に表示されている要素を辿る
await page.waitForSelector(workTreeItemsSelector);
const workTreeItems = await page.locator(workTreeItemsSelector).count();
await page.click(workTreeItemsSelector);
// 見開き表示の無効化 … 初回: 右下見開きボタンをクリックして無効化
const spreadButton = page.getByRole("button", { name: "見開き" });
await spreadButton.click();
await Promise.all([
spreadButton.waitFor({ state: "detached" }),
page.mouse.click(0, 720 / 2),
]);
await page.keyboard.press("ArrowRight");
// ページ数だけ画面送りを繰り返し行い、canvasをそのままキャプチャしていく
const files: Array<() => Promise<Blob>> = [];
while (files.length < workTreeItems) {
await page.waitForTimeout(1000);
const n = Math.min(2, Math.max(0, workTreeItems - 1 - files.length));
const canvas = page.locator("canvas").nth(n);
await canvas.waitFor({ state: "visible" });
const [width, height] = await Promise.all(
["width", "height"].map((d) => canvas.getAttribute(d).then(Number)),
);
await page.setViewportSize({ width, height });
await page.waitForTimeout(1000);
const buff = await canvas.screenshot();
files.push(async () => new Blob([buff], { type: "image/png" }));
process.stderr.write(".");
await page.keyboard.press("ArrowLeft");
}
return files;
}, },
loginEndpoints: ["https://www.dlsite.com/home/login"], loginEndpoints: ["https://www.dlsite.com/home/login"],
loginSuccessUrl: (url: URL) => url.origin === "https://www.dlsite.com", loginSuccessUrl: (url: URL) => url.origin === "https://www.dlsite.com",