動的生成されるサイトをseleniumでスクレイピング
動的生成されるサイトの判定方法
scrapyを使って簡単に判定できる
shellでサイトを読み込んで、欲しい情報の属性のxpathを取得
spiderでxpathをもって作成、実行
何も返していないなら動的生成される
それを使わない場合
サイトのソースを見る
classの値が読めないものになるなら基本動的生成されてる
seleniumを使ってスクレイピング
seleniumだけ使うスクレイピング自体できる、だだし中身を取り出す方法は不明(どこかに書いているような気がするが探したらないみたい)
今回はbs4とseleniumを合わせてスクレイピングするが、実際 CSSセレクターが使いずらい(個人的に)ので、scrapyをメインに使うつもり
とりあえずseleniumをインストール
code: install
pip install selenium
seleniumはいわばブラウザ偽装、人が実際サイトを閲覧するにサーバ側に見せかける。なのでブラウザがないと無理。
まずchroniumをインストール
code: chronium
# snapでインストールできる
snap install chronium
# snap版はflashのサポートがないので、それがいやならaptでインストール(今はすべてsnap版になっているみたい)
sudo apt install chromium-browser
chromedriverをインストール
code: chromedriver
sudo apt-get install chromium-chromedriver
seleniumによってブラウザ偽装
code: selenium
from selenium import * # だるいから全部インポート
options = Options()
options.add_argument('--headless') # 画面非表示
options.add_argument('--disable-gpu') # gpu不使用、bugがあるみたいで
options.add_argument('--no-sandbox') # 最高権限
options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36') # user-agent設定(随時更新する必要あるかも)
driver = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver", chrome_options=options) # ブラウザ起動
driver.get(url) # サイトにアクセス
sourcer=driver.page_source.encode("utf-8") # サイトが生成されるソースを取得
# スクレイピング処理
ajaxで作られたサイトの処理
動的生成されたサイトは大体 ajax で作られるので、jsの実行を待つ必要ある
time.sleepで十分だが、自分がほしいものがいつ生成されか分からない場合、seleniumを使って取得まで待てばいい
code:selenium wait
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver.get(url)
element = WebDriverWait(driver, 待ち時間).until(EC.presence_of_element_located((By.名前, "値")))
if element:
# 処理
BYのあとの名前はいろいろなものが指定できる
CLASS_NAME:クラス名
TAG_NAME:タグ名
CSS_SELECTOR: CSSセレクター
ID: ID タグ
LINK_TEXT: タグに囲まる文書
NAME: name タグ
PARTIAL_LINK_TEXT: タグに囲まれる文書、ここでは一部あっても探せる
XPATH: xpath
文字入力とクリック
偽装だから入力やクリックもできる
クリック
code: click
driver.find_element_by_名前("値").click()
time.sleep(待ち時間)
find_element_by_名前 
使い方はbyと同じ、大文字を小文字に変更して指定できる
find_element_by_xpath とか
click後seleniumの待ち動作ができないため、sleepを使用
文字入力
code: key
driver.find_element_by_名前("値").send_keys("内容")
基本はクリックと同じ
enter キーも偽装できる、Keys.ENTER で指定
beautifulsoupと組む(tripadvisorを例)
code: bs4
from bs4 import BeautifulSoup
from selenium import *
options = Options()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36')
driver = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver", chrome_options=options)
setup_url="https://www.tripadvisor.jp/Hotel_Review-g1066456-d1083444-Reviews-Sakura_Hotel_Hatagaya-Shibuya_Tokyo_Tokyo_Prefecture_Kanto.html"
driver.get(setup_url)
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "ChASv")))
if element:
html = driver.page_source.encode("utf-8")
soup = BeautifulSoup(html, 'lxml')
while True:
try:
review = soup.find_all("q", class_="XllAv H4 _a")
print(review)
driver.find_element_by_link_text('次へ').click()
time.sleep(1)
except (TimeoutException, WebDriverException) as e:
print("Last page reached")
break
driver.quit()
これでサクラホテルのレビューを全部取れる
#yang #matsushita #crawler