四季報データをWEBスクレイピングするスクリプトを作成したのですが、取得に約1日かかった。。。
証券コードを1000から9999までの連番で1件ずつ総当りして、四季報の情報あれば取得する処理を書いているのですが、 直列で実行して、1件あたり10秒くらいかかっているので、取得時間がすごい。8999×10=89990(約24.9時間)必要となる。
これではあんまりなので、マルチスレッドで並列に処理できるように変更を検討。
その時のメモです。環境はPython3.5.2。
pythonではthreadingモジュールが用意されているらしく、それを利用します。 利用方法としては、threadingモジュールをimportすればthreadクラスが用意されるので、 実行処理用のThreadインスタンスを作成して処理する方法か、 実行処理用のサブクラスを作成し、それで管理する方法があります。
17.1. threading — スレッドベースの並列処理 — Python 3.5.2 ドキュメント
サブクラス作成したほうが分かり易いかなあ、と今回はサブクラスを作成する方法を採用しています。
作成するサブクラスでは、init()とrun()メソッドをオーバライドできます。 それ以外はオーバライド不可。なので、initとrunの中に必要処理を書いてあげます。
生成したThreadオブジェクトは、start()メソッドを実行してあげると、 スレッドが活動化され、run()メソッドが呼び出されるとのこと。
例です。引数で与えた証券コードのyahooファイナンスページにアクセスし、会社名を取得する処理。
import os, time, threading from time import sleep from selenium import webdriver from pyquery import PyQuery class multiThread(threading.Thread): def __init__(self, code): threading.Thread.__init__(self) self.code = code def run(self): print("start: " + str(self.code)) scraping(self.code) print("end: " + str(self.code)) def scraping(code): browser = webdriver.PhantomJS(service_log_path=os.path.devnull) url = "http://stocks.finance.yahoo.co.jp/stocks/detail/?code=" + str(code) + ".T" browser.get(url) d = PyQuery(browser.page_source) msg = d.find("th.symbol").text() print(str(code) + ": " + msg) if __name__ == "__main__": thread1 = multiThread(7201) thread1.start() sleep(2) thread2 = multiThread(7202) thread2.start()
実行結果が以下。
start: 7201 start: 7202 7201: 日産自動車(株) end: 7201 7202: いすゞ自動車(株) end: 7202