pythonによる紳士達の性癖分析：Webスクレイピング編

### Webスクレイピングによる性癖収集
- 最近のpythonの勉強のおさらいも兼ねて、Webスクレイピングを実施してみる。
- AIに食わせるデータに使えるかもしれない(ただし使い道は考えていない)ので、某同人ゲーム販売サイトのランキングをたどってみる。
- 上位ランキング作品のタグのデータを取ることで、昨今の紳士達が嗜むところが顕になる……かもしれない。
- **調査対象が調査対象なので尾籠な単語が出てくることも多々あるがご容赦を。**
 
```py
# coding: UTF-8
import requests
from bs4 import BeautifulSoup
import re # 正規表現用
from time import sleep      # 待ち時間用
from pprint import pprint  # 改行付き配列出力
import csv

SCRAPING_INTERVAL_TIME = 5.5

ranking_category_total = (
    "http://*",
)

# ページネイションを含め、探査対象となるURL群を取得し配列に格納、返却する。
def getSearchTargetURLs(baseURLs) :

    for basePage in baseURLs :
        tgtpage = requests.get(basePage)
        pageUrls = []

        soup = BeautifulSoup(tgtpage.content, "html.parser")

        # ページネイションURLを取得
        pagenations = soup.select("li.ranking_pagination_item")

        # ページネイションが存在しない場合は単一ページだけなので入力URLのみリストに入れ続行
        if len(pagenations) == 0 :
            pageUrls.append(basePage)
            continue

        for pagina in pagenations :
            nexturl = pagina.find('a', href=True)
            pageUrls.append(nexturl['href'])

        # 重複要素を削除（順番を保持しない）
        pageUrls = list(set(pageUrls))

    pprint(pageUrls)

    return pageUrls

# 対象のプロダクトページが持つタグをすべて取得。タイトルと合わせて返す。
def getAttributeTags(tgturl) :
    tgtpage = requests.get(tgturl)

    sp = BeautifulSoup(tgtpage.content, "html.parser")

#    pageTitle = sp("h1")
    pageTitle = sp.select("h1")[0].text.strip()

    elems = sp.find_all(href=re.compile("work.genre"))

    tags = []

    for e in elems:
        tags.append(e.getText())

    print(pageTitle, end=" ")
    print(tags)
    return pageTitle, tags

# メイン処理スタート

# file open
f = open("RankingList.csv", "w")
writer = csv.writer(f, lineterminator="\n")
header = ["Title", "Tags"]
writer.writerow(header)

att_dict = {}

targetURLs = getSearchTargetURLs(ranking_category_total)

for url in targetURLs:

    # 対象URL : DLサイトランキング
    r = requests.get(url)

    # 第一引数＝解析対象　第二引数＝パーサー(何を元に解析するか：この場合はHTML)
    soup = BeautifulSoup(r.content, "html.parser")

    idx = 0
    # ランキングの順に従ってプロダクト名を取得する
    for rank in soup.select("dt.work_name"):

        idx+=1

        # タグ込文字列から個別ページへのURLを抽出（ひとつだけなのでfind_allでなくfind）
        tgturl = rank.find('a', href=True)

        # rankにはタグ等の情報も含まれているため、タイトルだけ抽出する
        # product_title = rank.getText()
        # product_title = product_title.strip()
        # print(str(idx) + " " + product_title + " " + str(tgturl['href']))

        # タグ抽出用関数に個別ページのURLを渡し、タグ群を取得
        title, tags = getAttributeTags(tgturl['href'])

        # {タグ, そのタグを発見した数}の形式で連想配列に格納。
        for tag in tags:
            att_dict[tag] = (att_dict.get(tag) or 0) + 1

        tags.insert(0, title)
        writer.writerow(tags)

        if (idx == 10) :
            break

        sleep(SCRAPING_INTERVAL_TIME)

    sleep(61)

f.close()

# 発見したタグとその数の一覧をCSV出力
f = open("TagList.csv", "w")
writer = csv.writer(f, lineterminator="\n")
header = ["Tag", "Count"]
writer.writerow(header)

csvline = []
for att in att_dict :
    csvline = [att, att_dict[att]]
    writer.writerow(csvline)

f.close()

```

- 基本的にやってることは単純に、「ランキングページへアクセス→ページネイションが存在する場合は遷移先も含めたURLをまとめて取得→各ランキング画面に掲載されている製品ページへ移動、タイトルとタグ群を取得」となる。
- ついでに「タイトル, タグ1, タグ2, タグ3...」を行としたCSVファイルと、「タグ, このタグの出現回数」をまとめたCSVファイルも出力。あとでAIに食わせるデータとして使えるかもしれない。
- タイトルに著作権はないと思うが、一応ほぼ伏せた形で出力例は以下のようになる。

```txt:RankingList.csv
Title,Tags
堕落***,女王様/お姫様,ラブラブ/あまあま,退廃/背徳/インモラル,中出し,処女
制服***,癒し,バイノーラル,少女,耳かき,ラブラブ/あまあま,ほのぼの
無口***,少女,セーラー服,電車,無理矢理,中出し,調教
【バ***,癒し,お姉さん,着物/和服,耳かき,中出し,フェラチオ
おい***,逆転無し,人外娘/モンスター娘,ファンタジー,丸呑み,逆レイプ,男性受け
(F***,バイノーラル,足コキ,パイズリ,言葉責め,焦らし,男性受け
ウラ***,ポリゴン,首輪/鎖/拘束具,ムチ/縄/蝋燭,売春/援交,調教,監禁
ニプ***,連続絶頂,戦士,バニーガール,アヘ顔,ツインテール,巨乳/爆乳
```
```txt:TagList.csv
Tag,Count
ポニーテール,6
輪姦,23
スーツ,1
メガネ,2
盗撮,1
陵辱,58
ヤクザ/裏社会,1
女王様/お姫様,9
口内射精,2
```
- ちなみにタグ出現数の上位はこんな感じに。みんなおっぱい好きだね。

![image](https://qiita-image-store.s3.amazonaws.com/0/135051/16015970-5f9f-0cf6-4a54-ae0eaecb1274.png)

### データの使い道
- 相関関係とか出せるのかな……
- たとえばこう、予想だけど「ASMR：耳かき」は同時に出現するパターンが多いだろう。「逆レイプ：言葉責め：男性受け」あたりもおそらく同様に。
 - 逆に「陵辱：ラブラブ/あまあま」には相関関係は生じないだろう。たぶん。
- なんかこう、せっかく集めたデータなんだから上手くpython使って分析してみたい。
- 頻出タグの組み合わせ調査は[次回へ続く](https://qiita.com/we-yu/items/d98050e0de94914b15b7)。

### 参考記事
- https://stackoverflow.com/questions/40716272/how-to-extract-h1-tag-text-with-beautifulsoup?rq=1
- https://qiita.com/tortuepin/items/4fbf29e42f05cb4b02a5
- https://qiita.com/Amtkxa/items/ae2196a007c58182f2d1
- https://note.nkmk.me/python-list-unique-duplicate/
- https://note.nkmk.me/python-pprint-pretty-print/
- https://qiita.com/a_t_a/items/50623aedf7e1dab3b876
- https://note.nkmk.me/python-function-return-multiple-values/
- https://docs.python.org/2/library/csv.html
- https://tonari-it.com/python-csv-writer-writerow/
- https://qiita.com/yonedaco/items/d0f65ca3dad2e085a51d