SHOTech Blog

プログラミングに関する記録です

pythonでaspxページのwebスクレイピング

pythonでwebスクレイピングをする際、.htmlページは問題ないのですが.aspxページの場合ちょっとつまずいたので残しておく。

de:code 2019のセッションスケジュールの取得

de:codeのセッションスケジュールが公開され自分の予定を立てれるようになったので、同行する人と参加予定のセッションの共有をしたくなったのがきっかけです。
ぱっと共有できる手段がなさそうだったので、いったんセッションリストを引っこ抜いて加工しようかなと思いました。 (160以上のセッションがあるので手でリストを作るのはナンセンスですし)
もしこうすれば手軽に共有できるよ!というのがあればぜひ教えてください。

BeautifulSoupだけではさくっとスクレイピングできない

www.microsoft.com

今回はこのページのセッションをリスト化して取得したいので、いつも通り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で一度描画してからスクレイピング

www.yoheim.net

ここを見ると下記の2つを使うといいらしいことが分かった

が、残念なことにphantomjsは開発が終了し、seleniumもphantomjsはサポート対象外になっていたので使えず…

Selenium + ChromeDriverで一度描画してからスクレイピング

qiita.com

ここを参考に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")

これでいったん各セッション情報をくくっている塊で取得して、その後各リストをループさせて目当ての情報を取得しました。
無事に欲しかった情報がリスト化できました。

pythonによるスクレイピングについてもっと詳しく知りたい方はこちらの書籍を参考にするとよいです

www.amazon.co.jp