pythonでaspxページのwebスクレイピング
pythonでwebスクレイピングをする際、.htmlページは問題ないのですが.aspxページの場合ちょっとつまずいたので残しておく。
de:code 2019のセッションスケジュールの取得
de:codeのセッションスケジュールが公開され自分の予定を立てれるようになったので、同行する人と参加予定のセッションの共有をしたくなったのがきっかけです。
ぱっと共有できる手段がなさそうだったので、いったんセッションリストを引っこ抜いて加工しようかなと思いました。 (160以上のセッションがあるので手でリストを作るのはナンセンスですし)
もしこうすれば手軽に共有できるよ!というのがあればぜひ教えてください。
BeautifulSoupだけではさくっとスクレイピングできない
今回はこのページのセッションをリスト化して取得したいので、いつも通りBeautifulSoupでスクレイピング。
<h2 class="c-heading session-id-title" data-bind="text: $data.Session.SessionID()">KN01</h2>
h2タグがセッションコードの目印になりそうなので、とりあえずまずはこれを取得してみる。
※もしHTTP Error 403: Forbiddenになる場合は権限がないことが原因であることが多いようなのでユーザエージェントをいじりましょう。
import urllib.request, urllib.error from bs4 import BeautifulSoup #decodeのセッションのページ url = "https://www.microsoft.com/ja-jp/events/decode/2019session/search.aspx" #ユーザエージェントをfirefoxにしてHTMLを取得 req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) html = urllib.request.urlopen(req).read() #HTMLを解析 soup = BeautifulSoup(html, "html.parser") #セッションコードを取得 print(soup.find_all("h2", class_="c-heading session-id-title"))
できたと持ったら何も返ってこなかった…
返ってきたHTMLを見てみたらh2タグとかなく、ソースのほとんどがjavascripだった。ページ開いて描画しないとダメっぽい。
PhantomJS + Seleniumで一度描画してからスクレイピング
ここを見ると下記の2つを使うといいらしいことが分かった
- selenium
- phantomjs
が、残念なことにphantomjsは開発が終了し、seleniumもphantomjsはサポート対象外になっていたので使えず…
Selenium + ChromeDriverで一度描画してからスクレイピング
ここを参考にseleniumとchromedriverをインストール。
時間とセッションコードとセッションタイトルをタブ区切りでTXTファイルに出力する。
import time import traceback from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.chrome.options import Options import chromedriver_binary import codecs options = Options() # ヘッドレスモードで実行する options.add_argument("--headless") driver = webdriver.Chrome(options=options) try: #decodeのセッションスケジュールのページを実行 driver.get("https://www.microsoft.com/ja-jp/events/decode/2019session/search.aspx") # 簡易的にJSが評価されるまで秒数で待つ time.sleep(5) # HTMLを解析する soup = BeautifulSoup(driver.page_source, "html.parser") #セッション情報のHTMLを抜き出してリスト化 slist = soup.find_all("div", class_="session-list-cards") # ファイルを開く f = codecs.open('decode.txt', 'w', encoding="utf-8") for s in slist: #各セッション情報からコード、時間、タイトルを抜き出す sessioncode = s.find("h2", class_="c-heading session-id-title").string sessiontime = s.find("li", class_="session-time-detail").string sessiontitle = s.find("h3").string #タイトル(最初に見つかった要素がタイトル) #ファイルに書き込む f.write( sessiontime + "\t" + sessioncode + "\t" + sessiontitle + "\r\n") f.close() except: traceback.print_exc() finally: # エラーが起きても起きなくてもブラウザを閉じる driver.quit()
TXTファイルができました。
9:30 - 12:00 KN01 基調講演 12:30 - 13:20 AI53 All About Chatbot! ~ チャットボット構築 & 実践 Chatbot Chalk Talk 12:30 - 13:20 CD06 しくみがわかる Azure Kubernetes Service (AKS) ~開発者目線で Kubernetes の基本を理解する~ ※以下略
今回は欲しい情報が格納されているh2タグやliタグなどはいたるところにあって、そのままでは不要なものも引っかけてしまいそうだったので
slist = soup.find_all("div", class_="session-list-cards")
これでいったん各セッション情報をくくっている塊で取得して、その後各リストをループさせて目当ての情報を取得しました。
無事に欲しかった情報がリスト化できました。