四季報データを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