目的
- PythonのSeleniumで、Google画像検索(エゴサーチ)した結果のうち、サムネイル画像上位20ファイルを、zipファイルにまとめる
背景
誰しも?自己紹介の資料を作るとき、一度はエゴサしたことと思うw
エゴサした結果を1つのファイルにまとめたら、何か面白い使い道があるのではないかと思い、作ってみた。
環境
- Windows11 バージョン22H2(OSビルド22621.963)
- Python3.9.1
- chrome 108.0.5359.125(Official Build) (64 ビット)
- chrome driver 108.0.5359.71
セットアップ
Pythonライブラリ
- ライブラリをインストールする
pip install urllib3
pip install requests
pip install pyperclip
pip install python-datauri
PythonのSelenium環境
- Selenium環境構築の説明は他に譲るとして、chromedriver.exeのパスは「C:\Git\traning\python\Web_scraping\driver\chromedriver.exe」とする
- たぶん以下のライブラリをインストールすればよいと思う
pip install selenium
pip install chromedriver-binary
pip install webdriver-manager
pip install webdrivermanager
使い方
- GitからSource code(zip)をダウンロードして、展開する
- 展開したパスが「c:\Git\traning\」とすると、「C:\Git\traning\python\Web_scraping\egoser_zipper.py」にツールがある
- egoser_zipper.pyは、以下のファイルに依存関係があるので、フォルダを移動する場合は一緒に移動する(実行するとegoser_zipper.txtファイルができる)
- crawling.py クローリングに使う
- chromeDriverHelper.py ChromeDriverを操作するヘルパーで、スクレイプやファイル保存に使う
- webFileListHelper.py 複数のwebFileHelperを操作するヘルパーで、ファイルの存在チェックやzip作成に使う
- webFileHelper.py URLを操作するヘルパーで、パスの作成やファイルの存在チェックに使う
- irvineHelper.py irvineを操作するヘルパーで、今回のツールでは使っていない、importだけされる
- uriHelper.py uriを操作するヘルパーで、パスの作成やDataURIの操作に使う
- 以下のコマンドラインを実行して、chromedriverを起動する
chrome.bat
- 以下のコマンドラインを実行して、エゴサzipperする
python egoser_zipper.py igapon
- 成功すると、archiveフォルダに「igapon.zip」が、workフォルダに「igapon:[ファイル名の禁則文字だけ全角にしたURL].html」ができる
- 漫画ビュアーなどでzipファイルを開いて、内容を確認する
コードの説明
- サイトや、ページのアドレスや、セレクタを定義する
egoser_ziper.py 25~47行目
site_url = f'https://www.google.com/search?q={my_name}'
site_selectors = {
'page_urls': [
(By.XPATH,
'//*[@id="hdtb-msb"]/div[1]/div/div[2]/a',
lambda el: el.get_attribute("href")
),
]
}
page_selectors = {
'title_jp': [(By.XPATH,
'//*[@id="REsRA"]',
lambda el: el.get_attribute("value")),
],
'title_en': [(By.XPATH,
'//*[@id="REsRA"]',
lambda el: el.get_attribute("value")),
],
'image_urls': [(By.XPATH,
'//*[@id="islrg"]/div[1]/div/a[1]/div[1]/img',
lambda el: el.get_attribute("src")),
],
}
- Crawlingクラスのインスタンスを作り、スクレイピングする
egoser_ziper.py 48~49行目
crawling = Crawling(site_url, site_selectors, 'egoser_ziper.txt')
crawling_items = crawling.get_crawling_items()
- スクレイピング結果からpage_urlsを取り出し、forループ処理を行う
- page_urlが除外リストに含まれていたら、以降の処理をスキップする
egoser_ziper.py 51~58行目
if 'page_urls' in crawling_items:
page_urls = crawling_items['page_urls']
for page_url in page_urls:
print(page_url)
if crawling.is_url_included_exclusion_list(page_url):
crawling.move_url_from_page_urls_to_exclusion_urls(page_url)
crawling.save_text()
continue
- ページのセレクタでスクレイピングする
- itemsから、image_urlsのスクレイピング結果を先頭から20個分取り出して、image_urlsに入れる
- titleを取り出し、urlを全角文字列url_titleに変換して、チェック用ファイル名を作る
egoser_ziper.py 59~65行目
items = crawling.scraping(page_url, page_selectors)
image_urls = crawling.take_out(items, 'image_urls')[0:20] # 先頭の20個は、DataURIで表示される
title = Crawling.validate_title(items, 'title_jp', 'title_en')
url_title = ChromeDriverHelper.fixed_file_name(page_url)
# フォルダがなかったらフォルダを作る
os.makedirs(WebFileListHelper.work_path, exist_ok=True)
target_file_name = os.path.join(WebFileListHelper.work_path, f'{title}:{url_title}.html')
- チェック用ファイルが既に存在していたり、image_urlsが空の時、以降の処理をスキップする(ただし、Google画像検索では、URLのクエリーが毎回違うようなので、毎回チェックをパスしてしまう)
- image_urlsを引数に、WebFileListHelperクラスのインスタンスを生成する
- chromedriverでローカルに保存する
- ローカルのファイルをzipファイルにまとめる
- zipファイル名をtitleに変更する
- ローカルのファイルを削除する
- チェック用ファイルを作る
- 除外リストにpage_urlを移動して、その情報を保存する
egoser_ziper.py 67~82行目
if not os.path.exists(target_file_name):
if image_urls:
print(image_urls)
web_file_list = WebFileListHelper(image_urls)
crawling.download_chrome_driver(web_file_list)
if not web_file_list.make_zip_file():
sys.exit()
if not web_file_list.rename_zip_file(title):
if not web_file_list.rename_zip_file(f'{title}:{url_title}'):
sys.exit()
web_file_list.delete_local_files()
# 成功したらチェック用ファイルを残す
ChromeDriverHelper().save_source(target_file_name)
# page_urlsからexclusion_urlsにURLを移して保存する
crawling.move_url_from_page_urls_to_exclusion_urls(page_url)
crawling.save_text()
おわりに
Google画像検索の上位20は、DataURIで返ってくることを知った。
21位以降の画像は、スクロールするとAjaxでロードされるらしい。
今回のツール作成は、勉強にはなったが、使い道が全く分からない。
関連リンク
参考サイト
- note.nkmk.me
- まくまくPythonノート
- dataclassを使って、Pythonで値オブジェクトを実装する
- selenium+pythonでログイン認証後に画像をダウンロード
- Selenium & Python で待機条件をカスタマイズするやり方
-
[Python]Base64でエンコードされた画像データをデコードする。
ツール作った後に、以下の記事を発見した。記事では元画像を取得するそうだが、今回私が作ったツールは、サムネイル画像を取得している。 - PythonスクレイピングでGoogle画像検索ページから画像を取得