Pythonメモ:scrapyとseleniumで複数のキーワードでスクレイピング

2018年11月1日

何が書いてあるか?

検索サイトを使い、複数の検索キーワードを設定してscrapyとseleniumを使ってスクレイピングする。
尚、本記事は最低限の動作確認が出来る程度にしか書いていない。

前準備

scrapyおよびselenium、chromeのヘッドレスブラウザー、chromeのドライバーはインストールしてある前提。
色んな記事があるので、参考にしながら入れる。

まずはプロジェクトの作成からSeleniumからHeadless Chromeを使ってみた https://qiita.com/orangain/items/db4594113c04e8801aad

Python, Scrapyの使い方(Webクローリング、スクレイピング) | note.nkmk.me https://note.nkmk.me/python-scrapy-tutorial/

あと、xpathについての知識も必要。

クローラ作成に必須!XPATHの記法まとめ
https://qiita.com/rllllho/items/cb1187cec0fb17fc650a

作成

まずはプロジェクトの作成から

scrapy startproject honyarara

すると、こんな感じでフォルダが出来る

honyarara
├── honyarara
│ ├── __init__.py
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── settings.py
│ └── spiders
│  └── __init__.py
└── scrapy.cfg

spidersディレクトリに移動し、spyderファイルを作成する

scrapy genspider honyarara_sp honyarara.com

出来たhonyarara_sp.pyの中を書いていく

class Honyarara_SpSpider(scrapy.Spider):
	name = 'honyarara_sp'
	allowed_domains = ['honyarara.com']
	start_urls = ['http://honyarara.com/']

	def start_requests(self):

		# 検索する複数のキーワードを設定。テストのため直に書いているが本番時は外部ファイルを読み込むかDBから読み込み
		s_keyword = ["テスト","バスト"]

		# キーワードの回数だけループ
		for item in s_keyword:

			# self.start_urlsはリスト形式なので[0]を指定。また、scrapyは同じアドレスを渡せないようフィルターがかけられているのでdont_filterを設定
			s_request = scrapy.Request(self.start_urls[0], dont_filter=True)

			# metaを使うことで後で述べるDownloaderMiddlewareと値を共有できる
			s_request.meta['serch_kw'] = item
			yield s_request

	def parse(self, response):

		#好きなパースの処理を書く
		for block in response.xpath('//h3'):
			print(block.xpath('text()').extract_first())
		pass

お次はmiddlewares.pyの中身を書いていく
まずは冒頭。

# セレニウム関連等をimport

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
import time
from scrapy.http import HtmlResponse

次にprocess_requestをいじる。

	# リクエストを送ってレスポンスを取得する前の処理を行うメソッド
	def process_request(self, request, spider):

		#ここでchromeのヘッドレスブラウザーの位置を指定
		CHROME_BIN = "/usr/bin/chromium-browser"

		#chromeをプログラムから操作するために必要なドライバーの位置を指定
		CHROME_DRIVER = os.path.expanduser('/usr/bin/chromedriver')
		options = Options()
		options.binary_location = CHROME_BIN
		options.add_argument('--headless')
		options.add_argument('--window-size=1280,3000')
		options.add_argument('--no-sandbox')

		# スパイダーファイルで設定した検索キーワードを変数に読み込む
		kw = request.meta['serch_kw']
		driver = webdriver.Chrome(CHROME_DRIVER, chrome_options=options)
		driver.get(request.url)

		# 検索窓を特定するためあらかじめchromeのデベロッパーツールでhtml構文を確認して適切なxpathを指定
		xpath = '//*[@id="lst-ib"]'

		# 検索窓を指定
		search = driver.find_element_by_xpath(xpath)

		#検索窓にキーワードを入力
		search.send_keys(kw)
		time.sleep(5)

		# リターンキーを押す
		search.send_keys(Keys.RETURN)
		time.sleep(5)

		# 返ってきたホームページを変数に格納
		html = driver.page_source

		# ホームページをパーサーに渡す
		return HtmlResponse(driver.current_url,
			body = html,
			encoding = 'utf-8',
			request = request)

settings.pyを変更する

# 下記の行をコメントアウトする
DOWNLOADER_MIDDLEWARES = {
'honyarara.middlewares.HonyararaDownloaderMiddleware': 543,
}

出来たファイルを実行。
ちなみに実行する名前はgenspiderをしたときに設定したもの。spiderファイルのnameの部分。

scrapy crawl honyarara_sp