RedandWhiteDays

赤、白、ときどき黒猫

DAY7: SeleniumとBeautifulSoup4を使ったPython3でのWebスクレイピング

始動から一ヶ月半以上、想定より遥かに時間がかかってしまったが、ようやくデータ収集を行うスクリプトの目処が立ったのでここに記す。



まず、今回のプログラムに使用したライブラリについて。
DAY1 : Scrape Shots - RedandWhiteDaysにおいては、urllib.requestをhtmlの取得に、reをデータの抽出に使うという原始的なデータの取得を行っていたが、最終的にSeleniumとBeautifulSoup4という外部ライブラリを組み合わせて使うことにした。



Seleniumはブラウザの自動操作を可能にするライブラリでPython以外にも様々な言語に対応している有名なライブラリだ。Seleniumを使うことにした理由は、Webスクレイピングをサーバー側に感知されにくくするためである。以前DAY4 : Request as Fox - RedandWhiteDaysでユーザーエージェントを偽装してhtmlファイルのGETリクエストを送る話をしたが、ブラウザを使ってアクセスした場合は、目的のhtmlファイルを読み込みながら必要な画像ファイルなどを適宜ダウンロードするという処理が行われるのに対し、urllib.requestからスクレイピングをした場合は、htmlファイルに対してしかGETリクエストが行われないため、UAを変更したところで明らかに不自然なアクセスログになってしまうという問題がある。その問題を解決するため、firefoxブラウザをSeleniumを使って起動し、htmlファイルを取得することにした。

from selenium import webdriver

driver=webdriver.Firefox()
driver.get(URL)
html=driver.page_source.encode('utf-8')
driver.quit()


BeautifulSoup4の採用に関しては理由は明確で、この方が明らかにデータの抽出および切り出しが容易になるからだ。
下の例ではまずclass名が'results'のdivタグの部分(results)を抜き出し、さらにそこからclass名が'home'のdivタグで囲まれた中からclass名が'goal'または'penalty'のspanタグを抜き出す、という作業を行っている。

from bs4 import BeautifulSoup

soup=BeautifulSoup(html,'html.parser')
results=soup.find('div',class_='results')
home=results.find('div',class_='home').find_all('span',class_=['goal','penalty'])


抜き出したタグから文字に当たる部分を抜き出したり、hrefなどの属性を取得するのも簡単に出来る。もちろん正規表現を用いたタグの指定にも対応している。

score=scorewrapper.find('span',class_='score').string#文字部分を取得
dct['x1']=float(line.get('x1'))#.get('x1')でx1属性を取得


これら2つのライブラリを軸に、1試合あたり5ページのクローリングを行い、およそ70 KBほどのデータを取得するようになった。



クローリングの時間間隔の調節は以下のような関数を噛ませることによって行った。

import time

def time_control(self,func,dct):
    start=time.time()
    func(**dct)
    end=time.time()
    duration=end-start
    if duration<10:
       time.sleep(10-duration)


funcが実際にスクレイピングを行う関数、dctがその関数の引数のディクショナリだ。
このように時間管理を一括して行うことで、例えばクロール間隔に乱数の要素を加えて少し複雑したい、などといった要望にも一箇所のコード変更で済む。
funcのように、別の関数の内部で実行してもらう関数のことをコールバック関数と呼ぶらしい。少し複雑な実行時間の計測をしたい際などにも便利そうなので覚えておこう。



以上、データ収集の目処が立った。
実際のデータ収集のステップは現在のノートPCで行うのではなく、クラスタマシンを用いて行おうかと思っているので、次回はroot権限を取らずにPython3の開発環境を構築することについての記事を書こうと思う。