最近、requests-html の存在を知ったので、共有したいと思います。
これまで beautifulsoup4 使ってたんですけど、javascript で動的にコンテンツが変わるページだと上手くいきませんでした。
でも、requests-html の README.md 読むと、javascript なページでもスクレイピングできそうな雰囲気あるじゃないですか!
早速やってみたいと思います。
インストール
まずはインストールから。
mac 使ってるんですけど、Mojave にしてしまったので、pyenv でこんなエラー出ました。
zipimport.ZipImportError: can't decompress data; zlib not available
そんなときは、こうじゃ!
sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
参考:[MacOS Mojave]pyenvでpythonのインストールがzlibエラーで失敗した時の対応
で、python3.6 でしか動かないって言ってるので、python3.6.7 とか入れてインストールします。
pyenv install 3.6.7
pipenv --python 3.6.7
pipenv install requests-html
そして実行環境立ち上げ。
pipenv shell
試してみる
steam のソフトの情報を取ってきたいと思います。
from requests_html import HTMLSession
session = HTMLSession()
r = session.get('https://store.steampowered.com/search/?sort_by=Released_DESC&os=win')
r.html.render()
[W:pyppeteer.chromium_downloader] start chromium download.
Download may take a few minutes.
100%|███████████████████████████████████████████████████████████████████████| 84299992/84299992 [00:14<00:00, 5986762.94it/s]
[W:pyppeteer.chromium_downloader]
chromium download done.
[W:pyppeteer.chromium_downloader] chromium extracted to: /Users/hoge/Library/Application Support/pyppeteer/local-chromium/575458
初回はレンダリングのためのブラウザをダウンロードします。
で、ソフトのタイトルを表示させたいと思います。
for t in r.html.find('.title'):
t.text
'永冻之壳 The Shell of Permafrost'
'The Lost Legends of Redwall: Escape the Gloomer Demo'
'Incubo Demo'
'Monsters & Anomaly'
'Elementary Arithmetic Game'
'Samozbor: Rebellion'
'Sumo'
'Slime-san: Creator'
'Black And Blue'
"Hunter's Trial: The fight never ends"
'Thick Light 3'
'ZDF History 360° – Tempelhof'
'Nya Nya Nya Girls (ʻʻʻ)_(=^・ω・^=)_(ʻʻʻ)'
'Ball Out'
'Island Invasion'
'Forex Trading Master: Simulator'
'WWII英雄列伝 最強の虎\u3000クルト・クニスペル Demo'
"Otiiz's adventure - Sushi Champ Demo"
'Adventure Boy Cheapskate DX'
'Iridescence'
'Warhalla'
'Hentai Square Puzzle'
'Black Annex'
'Proto-G Demo'
'Escape Velocity'
おー、きたきた。
ちなみに、beautifulsoup だとこうなります。
import urllib.request, urllib.error
from bs4 import BeautifulSoup
html = urllib.request.urlopen(url='https://store.steampowered.com/search/?sort_by=Released_DESC&os=win')
soup = BeautifulSoup(html, "html.parser")
for t in soup.select('.title'):
t.text
'永冻之壳 The Shell of Permafrost'
'The Lost Legends of Redwall: Escape the Gloomer Demo'
'Incubo Demo'
'Monsters & Anomaly'
'Elementary Arithmetic Game'
'Samozbor: Rebellion'
'Sumo'
'Slime-san: Creator'
'Black And Blue'
"Hunter's Trial: The fight never ends"
'Thick Light 3'
'ZDF History 360° – Tempelhof'
'Nya Nya Nya Girls (ʻʻʻ)_(=^・ω・^=)_(ʻʻʻ)'
'Ball Out'
'Island Invasion'
'Forex Trading Master: Simulator'
'WWII英雄列伝 最強の虎\u3000クルト・クニスペル Demo'
"Otiiz's adventure - Sushi Champ Demo"
'Adventure Boy Cheapskate DX'
'Iridescence'
'Warhalla'
'Hentai Square Puzzle'
'Black Annex'
'Proto-G Demo'
'Escape Velocity'
・・・・・・・・あれ、見れる(・_・;)
もう一度
もうちょっとレンダリングに時間かかりそうなページにする必要があるっぽいです。
ので、先程は検索結果の1ページ目を使いましたけど、次は後の方(1000ページ目とか)にしてみたいと思います。
まずは requests-html。
session = HTMLSession()
r = session.get('https://store.steampowered.com/search/?sort_by=Released_DESC&page=1914&os=win')
r.html.render()
for t in r.html.find('.title'):
t.text
'AstroPop Deluxe'
'Big Money! Deluxe'
'Iggle Pop Deluxe'
'Rocket Mania Deluxe'
'Hammer Heads Deluxe'
'Dynomite Deluxe'
'Talismania Deluxe'
'Pizza Frenzy Deluxe'
'Typer Shark! Deluxe'
'Heavy Weapon Deluxe'
'Xpand Rally'
'Uplink'
'Iron Warriors: T - 72 Tank Command'
'X3: Reunion'
'X2: The Threat'
'The Ship: Murder Party'
"Disciples II: Gallean's Return"
'Disciples II: Rise of the Elves'
'Jagged Alliance 2 Gold'
'Half-Life 2: Episode One'
'SiN Episodes: Emergence'
'Shadowgrounds'
'Half-Life Deathmatch: Source'
'Shadowgrounds Demo'
'Earth 2160'
次は beautifulsoup。
html = urllib.request.urlopen(url='https://store.steampowered.com/search/?sort_by=Released_DESC&page=1914&os=win')
soup = BeautifulSoup(html, "html.parser")
for t in soup.select('.title'):
t.text
お、何も出てこない!
ということは、javascript はレンダリングされてない!(たぶん)
まとめ
- requests-html 使うとスクレイピングが捗るよ
ちなみに、beautifulsoup でも chromium と wait で頑張れば javascript のページのスクレイピングできたと思います(昔、やった気がする)。
まぁでも requests-html 使うと簡単に実装できそうなので、今後はこっちを使うのが良いと思いました。