🏕️

マンガサイトにつひての色々な事情 02

2021/07/06に公開

tags: Ruby SQLite3 国会図書館 cloudflare scraping

マンガサイトにつひての色々な事情を看るからのつづきです。
https://zenn.dev/kurocat/articles/96f88ef6d8d71b

ここまでのこと

漫画サイトには大きく分けて二種類ある。一方が違法サイトで、もう一方が合法サイトである。

ここでは、違法サイトについて調べてみたい。

マンガサイト観測 1

違法と思われる漫画サイトの中でシンプルな構造のオンラインリーディング型のサイト . . . マンガ Thank をターゲットに観測す。(注)マンガ Thank というサイトは存在せず、こころの中に存在すべし。

マンガ家の方(もしくは、プログラミングより海賊サイトの明瞭なデータについての興味をお持ちの方)は、「マンガサイトにつひての色々な事情 03 」へ進まれることをおすすめします。

違法と思われるマンガ Thank(仮称)の HTML の構造をよく確認する

違法と思われるコンテンツである漫画のスキャンデータ、もしくは電子書籍マンガからのコピーである画像ファイルは、概ね cloudflare 社[1]のキャッシュのイメージファイルが <img> で直接指定されている。
また、lazy loading[2] で読み込まれている。
仕組みとしてはページに別のサーバーにある WordPress で管理された画像群の画像ファイル(ここが cloudflare のキャッシュになっているということで、それは当該のファイルの URL を逆引きしてドメインからドメイン所有者をわりだすと cloudflare になっているということ。いずれ図説したい。)をページ内に lazy loading で読み込んで表示させていることが確認できる。

https://urlscan.io/

Cloudflare ドメイン

Cloudflare, Inc.(クラウドフレア)とは [https://ja.wikipedia.org/wiki/Cloudflare]

シンプルなので理解しやすいはずである。
つまり、オンラインリーディング型のサイト、マンガ Thank(仮称)のメインのコンテンツは画像だけなので、その画像がページ内にたとえば 100 点収まっているだけというシンプルな構造で、付加的にアップデート日時がタグで囲まれて配置されている。これはマンガ Thank(仮称)のシステム管理者用にあるのだと考えられる。 アップデート日時の情報は、マンガ Thank(仮称)のマンガコンテンツを表示するページのソースコード表示で確認できるが、ブラウザでレンダリングされた表示では見えないようにはなっている。

ひとつめのデータベーステーブル [tbl_manga]

このマンガ Thank(仮称)ページの構造から考えて、以下のようなデータベースを作ることにする。

    mangathank.db > tbl_manga

[tbl_manga]

    id INTEGER PRIMARY KEY,
    title text,
    url text,
    updated_datetime datetime,
    author text,
    book_title text

カラム title の値は、ページにあるタイトルを抽出したもの。
カラム url の値は、コンテンツの埋め込まれたページの URL で、ページに埋め込まれた画像ファイルの URL ではない。画像の URL はこのステップでは収集しない。
画像ファイルがすべて cloudflare 管轄のドメインのものを使用されているのか確認したい段階で URL を収集することになるのかもしれないが、それ自体は非常に簡単にできる。ここでは割愛。

https://zenn.dev/kurocat/articles/55565f019754cb

仕組み上、この url の値はユニークである。つまり重複はない。title が重複することがあっても url は重複しない。なぜかは考えればすぐにわかるはずだ。 updated_datetime は、ページソースコードにあるアップデートした日時を収める。ただし、これが正確なのかは不明なので、後にプロファイルするための参考にするために抽出する。 その他は、ターゲットのページから抽出するのではなく、抽出されたデータをもとに生成する。

Scraping data from the site 🍎

sample:

webdriver_mangathank.rb
urls = generated

require 'sqlite3'
require 'csv'
require 'time'
require 'date'

SQL =<<EOS
create table tbl_manga (
    id INTEGER PRIMARY KEY,
    title text,
    url text,
    updated_datetime datetime,
    author text,
    book_title text
);
EOS

db = SQLite3::Database.open "mangathank_new.db"
db.execute(SQL)
db.close

100.times do |loop|

    db = SQLite3::Database.open "mangathank_new.db"

    4.times do |loop|
        driver.get(urls)
        #sleep 1
        flag = []
        URL = driver.current_url
        flag = db.execute("select id from tbl_manga where url='#{URL}'")
        #p flag
 
        if flag.any? then
            next
        else
            CSV.open('mangathank_TEMP.csv','a+') do |data|
                title = driver.find_element(:class_name, 'entry-title')
                updated = driver.find_element(:class_name,'updated')
                updated_datetime = updated.attribute('datetime')
                title.text.to_s.rstrip!

                pp title.text

                data << [URL,title.text,updated_datetime]
            end
        end
    end
    
    if File.exist?("mangathank_TEMP.csv") then
        CSV.foreach('mangathank_TEMP.csv') do |line|
            count += 1
            url = line[0]
            url.to_s.gsub!(/\'/,"\'\'")
            title = line[1]
            author_name = title.slice(/(?<=\[).*?(?=\])/)
            updated_datetime = line[2]
            updated_datetime.to_s.gsub!(/\'/,"\'\'")
            id = count
            title.to_s.gsub!(/\'/,"\'\'")

            #puts title
            #puts author_name 
            
            db.execute("insert into tbl_manga (id, title, url, updated_datetime ) values('#{id}', '#{title}','#{url}','#{updated_datetime}')")
            
            if author_name != nil then #
                author_name.gsub!(/\'/,"\'\'")
                
                pp author_name

            end

            book_title = title.slice(/((?<=\]).+?$)/)
            if book_title then
                book_title.gsub!(/((?=第).*(巻|卷))/,'')
                book_title.gsub!(/((?=第).*話)/,'')
                book_title.gsub!(/(.(?<=\()文庫版(?=\)).)/,'')
                book_title.gsub!(/(.(?<=\[)文庫版(?=\]).)/,'')
                book_title.gsub!(/文庫版/,'')
                book_title.gsub!(/(.(?<=\()完(?=\)).)/,'')
                book_title.gsub!(/(.(?<=【).*(?=】).)/,'')
                book_title.gsub!(/(.(?<=\[).+?(?=\]).)/,'')
                book_title.gsub!(/\'/,"\'\'")
                book_title.lstrip!
                book_title.rstrip!
            else
                book_title = title
            end
 
            pp book_title

            db.execute("update tbl_manga set author = '#{author_name.to_s}', book_title = '#{book_title.to_s}' where id = '#{id}' ;")
        end

        db.close
        system("rm -r mangathank_TEMP.csv")
    else 
        next
    end
    db.close
end

目標

ゴール設定は、オンラインリーディング型のサイトであるマンガ Thank(仮称)にコンテンツとして使用されている漫画について、すべて権利者を割り出して、並べて見ること。

結果
https://crieit.net/posts/4daedd75f0cec1b328d4e661d9337bd3

たとえば、コミックスであれば、たいていの紙の本は出版社が発行しているので、その出版社名、書籍データを、違法にアップロードされたものから、できるだけ正確に逆引きして表示するまでがひとまずの目標とする。曖昧なメタデータから、正確なメタデータへ変換するということ。

書籍データは ISBN[3] をともなったものが多いが、全てではないのと、電子書籍は書籍という枠には入れられていないために ISBN での管理を外れていても例外とは云えない。
おおかたの書籍検索システムは ISBN コードを主軸としているので、ISBN を使って書籍データを問い合わせる仕組みになっているが、これでは要件に適していないので、 本のタイトルから書籍データを問い合わせることが可能なシステムの API を使い、これを実現する

つづく ... マンガサイトにつひての色々な事情 03

関連記事

https://qiita.com/dauuricus/items/563cbcc9776f66cb672e

https://zenn.dev/kurocat/articles/55565f019754cb

https://zenn.dev/kurocat/articles/96f88ef6d8d71b

脚注
  1. 空中分解…海賊版サイト対策検討会はなぜ迷走したか https://www.yomiuri.co.jp/fukayomi/20181017-OYT8T50059/2/ ↩︎

  2. A lightweight but powerful delayed content, image and background lazy-loading plugin for jQuery & Zepto http://jquery.eisbehr.de/lazy/example_basic-usage ↩︎

  3. 日本図書コード管理センター https://isbn.jpo.or.jp/index.php/fix__about/fix__about_3/ ↩︎

Discussion