事前準備
1.Scrapyのプロジェクトを作成する。
1 2 3 |
scrapy startproject 対象サイト名 cd 対象サイト名 scrapy genspider 任意のspider名 www.xxx.com(サイトURL) |
2.projects/プロジェクト配下にchromedriverを配置します。
chromedriverは自分のお使いのChromeのバージョンを調べて検索すれば入手可能です。
3.scrapy-seleniumの設定をする。
以下の公式ページに行きます。Configurationのところに記載がある「1」と「2」の記述をsettings.pyに貼り付けます。
1 2 3 4 5 6 7 |
SELENIUM_DRIVER_NAME = 'chrome' SELENIUM_DRIVER_EXECUTABLE_PATH = r'自分のPCのchromedriverのパス' SELENIUM_DRIVER_ARGUMENTS=['-headless'] # '--headless' if using chrome instead of firefox DOWNLOADER_MIDDLEWARES = { 'scrapy_selenium.SeleniumMiddleware': 800 } |
なお、firefoxになっていますが、chromeが基本だと思いますのでSELENIUM_DRIVER_NAMEは「chrome」とSELENIUM_DRIVER_EXECUTABLE_PATHは「r'自分のPCのchromedriverのパス'」にそれぞれ書き換えます。(which('chromedriver')という指定でも環境によってはいけるっぽいですが自分の環境だと直接指定しないと動きませんでした。)
その他設定
scrapy-seleniumを使う場合でも最低限のスクレイピングマナーとしてこの辺の設定はしておくようにしましょう。
1 2 3 |
DOWNLOAD_DELAY = 5 # ダウンロード間隔を秒数で指定 FEED_EXPORT_ENCODING = 'utf-8' # 文字化けしないように設定しておく ROBOTSTXT_OBEY = True # robots.txtがある場合はそれに従う設定 |
検索ボックスに入力するサンプル実装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
import scrapy from scrapy_selenium import SeleniumRequest from time import sleep from selenium.webdriver.common.keys import Keys from scrapy.selector import Selector class XXXPythonSpider(scrapy.Spider): name = "spider名" # 最初のリクエストはstart_requestsで送る。 def start_requests(self): yield SeleniumRequest( url='サイトのURL', wait_time=3, callback=self.parse ) # spiderではレスポンスはparseメソッドで受ける。 def parse(self, response): driver = response.meta['driver'] search_bar = driver.find_element_by_xpath('検索ボックスのXpath') search_bar.send_keys('python') sleep(1) driver.save_screenshot('xxx.png') search_bar.send_keys(Keys.ENTER) sleep(3) w = driver.execute_script('return document.body.scrollWidth') h = driver.execute_script('return document.body.scrollHeight') driver.set_window_size(w,h) driver.save_screenshot('yyy.png') html = driver.page_source sel = Selector(text=html) for elem in sel.xpath('検索結果のXPath'): yield{ 'title': elem.xpath('タイトルのXPath').get(), 'URL': elem.xpath('URLのXPath').get() } |
start_requests
scrapy-seleniumを使う場合はseleniumのリクエストとして処理する必要があるのでこれをオーバーライドします。start_urls属性で指定されたURLに対してリクエストを送信します。(ただ、本サンプルでは後続のSeleniumRequestにてurlを別途指定しているので不要になります。)
wait_time
待ち時間です。上記サンプルでは3秒を指定しています。
response
データ型は「scrapy.http.response.html.HtmlResponse」クラスになります。
driver = response.meta('driver')
リクエストしたdriverの情報はレスポンスのmetaデータの中に格納されているので上記のように取り出すことが可能です。このドライバーの情報をもとにxpathやcssで情報を取得したりします。
ここで取得したdriverのデータ型は「selenium.webdriver.chrome.webdriver.WebDriver」というclassになっています。
driver.save_screenshot('xxx.png')
scrapy-seleniumはヘッドレスブラウザが基本なので処理の最後でスクリーンショットを取得するようにする方が無難でしょう。
search_bar.send_keys(Keys.ENTER)
Enterキーを押すアクションです。(clickやsubmitなどのボタンを押すアクションでも良いかもしれません)
driver.set_window_size(w,h)
execute_scriptで実行したJavaScriptで画面サイズを取得した結果を設定しています。通常だと画面のスクリーンショットを取得しても一部しか取得できないのですが、こうすることで画面全体のスクリーンショットを取得できます。
html = driver.page_source、sel = Selector(text=html)
driverは最初に取得したHTMLしか持たないのでその後検索アクションを行った後のHTMLに関しては別途アクション後に取得してあげる必要があります。上記のようにhtmlを取得した後にSelectorオブジェクトに変換してあげる必要があります。
次のページを取得する
上の例のように一覧画面のように複数ページある場合の情報取得処理は以下のようになります。都度SeleniumRequestをしてあげて、次のページがある場合のみ再度SeleniumRequestをしてあげるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def parse(self, response): driver = response.meta['driver'] yield SeleniumRequest( url=driver.current_url, wait_time=3, callback=self.parse_next ) def parse_next(self, response): for elem in sel.xpath('検索結果のXPath'): yield{ 'title': elem.xpath('タイトルのXPath').get(), 'URL': elem.xpath('URLのXPath').get() } next_page = response.xpath('次へボタンのXPath').get() if next_page: next_url = response.urljoin(next_page) yield SeleniumRequest( url=next_url, wait_time=3, callback=self.parse_next ) |
driver.current_url
現在のURLを再度リクエストしています。
next_url = response.urljoin(next_page)
SeleniumRequestは絶対パス指定が必要になるのでこのように変換してあげる必要があります。
この記事へのコメントはありません。