🦍
pythonで yahoo 画像検索結果のプレビュー画像(ゴリラ)をかき集める
yahooでゴリラの画像検索した際のプレビュー画像を集めたくなり
ウホウホしてみました。
python version
python 3.7
やりたいこと
- yahoo で「ゴリラ」の画像を検索
- 全てのプレビュー画像を「gorira_images」というディレクトリに保存
事前確認
1. 検索結果のURLを確認
ブラウザでyahooにアクセスして「ゴリラ」の画像を検索し、検索結果のURLを確認。
※今回はchrome使ってます
↓URL↓
2. 検索結果の画面を確認
画面を下にスクロールしていくと、次の画像が表示されていく仕様でした。
さらに画像がある場合は「もっと見る」というボタンが出現し、
「もっと見る」を押下するとさらにスクロールできるようでした。
「もっと見る」というボタンが出現しなくなるまでスクロールを続ければ
全てのプレビュー画像を表示できそうです。
3. 必要な要素の格納場所を探す
Chromeのデベロッパーツールを使い、探索していきます。
- プレビュー画像のリンク
div.sw-Thumbnail.sw-Thumbnail--tile > figure > a > img' の中の’src’にあるようです。
- 「もっと見る」ボタン
'div.sw-MoreButton > div > button' のようです。
愚直にコードを書いていく
使用するモジュール
事前確認の結果を踏まえ、以下を使用することにしました。
import os
import urllib.request
from selenium import webdriver
from time import sleep
module | 用途 |
---|---|
os | 保存先ディレクトリの作成やファイル名の取得で使用 |
urllib.request | リンクの画像を保存 |
selenium | 検索結果をスクロールする必要があったので使用 |
time | スクロール中にsleep関数で待たせるために使用 |
画像の保存先ディレクトリがなければ作成する
save_dir = 'gorira_images'
if not os.path.exists(save_dir):
os.makedirs(save_dir)
selenium webdriver で検索結果画面にアクセス
#### 検索結果のURL
url = 'https://search.yahoo.co.jp/image/search?ei=UTF-8&fr=mcafeess1&p=%E3%82%B4%E3%83%AA%E3%83%A9'
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(
executable_path='/Users/ireba-pc/webdriver/chromedriver',
options=options)
driver.get(url)
driver.implicitly_wait(2)
検索結果画面をスクロール
事前確認の通り、「「もっと見る」というボタンが出現しなくなるまでスクロールを続ければ全てのプレビュー画像を表示できそう」なので、その通り動かします。
### while True でスクロールを続ける
while True:
#### execute_script メソッドを使用すると、ロードしたページ上でjavascriptを実行できます。
#### return document.body.scrollHeight でページ全体の高さを取得
height = driver.execute_script('return document.body.scrollHeight')
#### scrollTo で取得した高さまでスクロール
driver.execute_script(f'window.scrollTo(0, {height})')
sleep(2)
#### try exceptで「もっと見る」ボタンが無い場合の処理を書きます
try:
more_button = driver.find_element_by_css_selector('div.sw-MoreButton > div > button')
more_button.click()
except:
#### 先に取得した「height(ページ全体の高さ)」が現在の値と変わっていなければ、スクロール完了と見なし、whileを抜けます
new_height = driver.execute_script('return document.body.scrollHeight')
if height == new_height:
break
画像を保存
#### 全てのimgタグを取得
img_tags = driver.find_elements_by_css_selector('div.sw-Thumbnail.sw-Thumbnail--tile > figure > a > img')
#### 取得した img タグをインデックス付きでforで回す
for idx, img_tag in enumerate(img_tags):
#### src を取り出す
img_url = img_tag.get_attribute('src')
#### basenameでファイル名を取得
img_name = os.path.basename(img_url)
#### urlopenでリンク先の画像を読み込む
img_data = urllib.request.urlopen(img_url).read()
#### 定番のファイル保存処理
#### ファイル名が異常に長いのがあるよーと、エラーが出たのでexceptしておきました
try:
with open(f'{save_dir}/{idx}_{img_name}', mode="wb") as f:
f.write(img_data)
except OSError as e:
if e.errno == 63:
#### ファイル名が~とエラーが出たら、ファイル名を「インデック番号.拡張子」として保存
_, img_ex = os.path.splitext(img_name)
with open(f'{save_dir}/{idx}{img_ex}', mode="wb") as f:
f.write(img_data)
else:
pass
こんな感じになりました
import os
import urllib.request
from selenium import webdriver
from time import sleep
save_dir = 'gorira_images'
if not os.path.exists(save_dir):
os.makedirs(save_dir)
url = 'https://search.yahoo.co.jp/image/search?ei=UTF-8&fr=mcafeess1&p=%E3%82%B4%E3%83%AA%E3%83%A9'
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(
executable_path='/Users/ireba-pc/webdriver/chromedriver',
options=options)
driver.get(url)
driver.implicitly_wait(2)
while True:
height = driver.execute_script('return document.body.scrollHeight')
driver.execute_script(f'window.scrollTo(0, {height})')
sleep(2)
try:
more_button = driver.find_element_by_css_selector('div.sw-MoreButton > div > button')
more_button.click()
except:
new_height = driver.execute_script('return document.body.scrollHeight')
if height == new_height:
break
img_tags = driver.find_elements_by_css_selector('div.sw-Thumbnail.sw-Thumbnail--tile > figure > a > img')
for idx, img_tag in enumerate(img_tags):
img_url = img_tag.get_attribute('src')
img_name = os.path.basename(img_url)
img_data = urllib.request.urlopen(img_url).read()
try:
with open(f'{save_dir}/{idx}_{img_name}', mode="wb") as f:
f.write(img_data)
except OSError as e:
if e.errno == 63:
_, img_ex = os.path.splitext(img_name)
with open(f'{save_dir}/{idx}{img_ex}', mode="wb") as f:
f.write(img_data)
else:
pass
driver.quit()
実行すると、プレビューゴリラが605体、保存されました。
$ find ./gorira_images/ -size +0 -type f | wc -l
605
中身も見ておきます。
壮観です。神々しいです。
Discussion