This site is a mirror of ama.ne.jp.

ピクシブの小説ランキングをスクレイピングする

2017年になってもインターネットはなかなか消えないので、たまにはスクレイピングの練習をしたいと思います。

どういうものがいいでしょうかね。練習ですから、ある程度複雑なサイト……例えば、認証が必要なサイトがいいですね。

というわけで、今回はpixiv小説 R-18ウィークリーランキングをスクレイピングしてみようと思います。

ログインする

ランキングページを表示するためにはログインが必要です。今日はcurlを使ってやってみましょう。

curlは受け取ったcookieをファイルに書いたり、ファイルから読み込んだcookieを送信したりできます。まず、-cオプションを使って、ログインに必要なセッションを取得しましょう。

curl -c cookie.txt https://accounts.pixiv.net/login > login.html

cookie.txtの中は下のような感じで、受け取ったcookieが記録されていることがわかります。

# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_.pixiv.net    TRUE    /   FALSE   9999999999  PHPSESSID   xxxxx
.pixiv.net              TRUE    /   FALSE   9999999999  p_ab_id     xxxxx
.pixiv.net              TRUE    /   FALSE   9999999999  p_ab_id_2   xxxxx

フォームには不正なログインを防止するためのパラメータが付いていたりするので、それも取り出します。xmllintがない人は、適当にBeautiful Soupnokogiriでも使ってください。nkfがなければ手や好きなスクリプト言語でどうぞ。

xmllint --xpath '//form//input[@type="hidden"]/@name' --html login.html | \
  sed -e 's/ name=\("\([^"]*\)"\|\'\([^\']*\)\'\)/\2\3\n/g' | \
  nkf -WwMQ | tr "=" "%" > keys.txt

xmllint --xpath '//form//input[@type="hidden"]/@value' --html login.html | \
  sed -e 's/ value=\("\([^"]*\)"\|\'\([^\']*\)\'\)/\2\3\n/g' | \
  nkf -WwMQ | tr "=" "%" > values.txt

さて。全てのパラメータが揃ったので、IDとパスワードをくっつけて送信しましょう。-bオプションでさっき保存したcookieを使い、-cオプションで受け取ったcookieを保存します。

echo "pixiv_id" >> keys.txt
echo "password" >> keys.txt
echo YOUR_PIXIV_ID >> values.txt
echo YOUR_PASSWORD >> values.txt
curl -b cookie.txt -c cookie.txt --data (paste -d "=" keys.txt values.txt | tr "\n" "&") https://accounts.pixiv.net/login

リダイレクトを受け入れる-Lオプションを付けていないため、成功すると無が返ってきます。cookie.txtdevice_tokenがあれば、この章の作業は完了です。

ピクシブの最も不要な機能の1つとして、オプトアウト不可のログイン通知メールがあり、これでも成否が分かります。よかったね。

ページを取得する

ここからは簡単です。全てのリクエストはログインしたユーザーの権限で行うことになります。ウィークリーランキングを上から10件取得してみましょう。

curl -L -b cookie.txt "https://www.pixiv.net/novel/ranking.php?mode=weekly_r18" > r18_weekly_ranking.html

xmllint --xpath '//div[@class="novel-right-contents"]//h1[@class="title"]/a/@href' --html r18_weekly_ranking.html | \
  sed -e 's/ href=\("\([^"]*\)"\|\'\([^\']*\)\'\)/\2\3\n/g' | \
  sed -e "s#^#http://www.pixiv.net#g" | head -n10 > ranking_urls.txt

xmllint --xpath '//div[@class="novel-right-contents"]//li[@class="author"]/a/@data-user_name' --html r18_weekly_ranking.html | \
  sed -e 's/ data-user_name=\("\([^"]*\)"\|\'\([^\']*\)\'\)/\2\3\n/g' | head -n10 ranking_authors.txt

上から10件が気に入らなければ、tailしたりオプションを変えたりしてください。

整形する

記事に掲載しやすいように、Markdownの表形式にしてみましょう。

seq 1 10 > numbers.txt
echo '| ID | 小説のURL | 作者名 |' > table.md
echo '|:- |:- |:- |' >> table.md
paste -d '|' numbers.txt ranking_urls.txt ranking_authors.txt | \
  sed -e 's/|/ | /g' | sed -e 's/^/| /g' | sed -e 's/$/ |/g' >> table.md

結果はこう。

| ID | 小説のURL | 作者名 |
|:- |:- |:- |
| 1 | http://www.pixiv.net/novel/show.php?id=8195281 | 祭 |
| 2 | http://www.pixiv.net/novel/show.php?id=8194128 | 茉莉花 |
| 3 | http://www.pixiv.net/novel/show.php?id=8198107 | 夏子 |
| 4 | http://www.pixiv.net/novel/show.php?id=8197609 | みとい |
| 5 | http://www.pixiv.net/novel/show.php?id=8196278 | 斎藤 |
| 6 | http://www.pixiv.net/novel/show.php?id=8195245 | なめこ |
| 7 | http://www.pixiv.net/novel/show.php?id=8196089 | 都 |
| 8 | http://www.pixiv.net/novel/show.php?id=8189511 | Kay |
| 9 | http://www.pixiv.net/novel/show.php?id=8195912 | 香子 |
| 10 | http://www.pixiv.net/novel/show.php?id=8189382 | あき |

使う

ランキングのデータ。記事での仮IDと小説URL、作者名を示す。

ID 小説のURL 作者名
1 http://www.pixiv.net/novel/show.php?id=8195281
2 http://www.pixiv.net/novel/show.php?id=8194128 茉莉花
3 http://www.pixiv.net/novel/show.php?id=8198107 夏子
4 http://www.pixiv.net/novel/show.php?id=8197609 みとい
5 http://www.pixiv.net/novel/show.php?id=8196278 斎藤
6 http://www.pixiv.net/novel/show.php?id=8195245 なめこ
7 http://www.pixiv.net/novel/show.php?id=8196089
8 http://www.pixiv.net/novel/show.php?id=8189511 Kay
9 http://www.pixiv.net/novel/show.php?id=8195912 香子
10 http://www.pixiv.net/novel/show.php?id=8189382 あき

色々読んで引用しながら感想でも書こうと思ったんですが、なんかpixivの調子が悪そうなのでやめました。

おわりに

人生経験豊富な法律用語満載アカウントになりたい。人生経験豊富な法律用語満載アカウントになりたいよ……どうやればあんな風にカッコよく自分のルールを話せるようになれるのか……教えてよ……。

おわりです。今日の完成品はこちら。動かす前にfishを入れてください。

「読んだ」を押すと、あなたがボタンを押した事実を明示的に通知してこのページに戻ります。このページに戻ってからブラウザの「戻る」ボタンを押すと、何度か同じページが表示されることがあります。