ポケモン図鑑をスクレイピング

ポケモン図鑑はポケモンの強さなどのステータスを調べるのにとても便利です。しかし、一覧の情報は載っていませんので、スクレイピングを使って全ポケモンのステータスを取得してみたいと思います。

事前調査

  • スクレイピングするツールはSecectimuが良さそうだ
  • ポケモン図鑑のデータはJSONファイルになっていそう
    https://zukan.pokemon.co.jp/zukan-api/api/detail/003

参考サイト

環境構築

homebrewでchromedriverをインストール

chromedriver: 103.0.5060.53がインストールされた。

brew install chromedriver

pythonの仮想環境などをインストール

pyenvとpipenvでPythonの環境構築をする – Mac

pipenvについては
【図解】作業が倍速!pipenvの使い方【Python】

brew install pyenv
brew install pipenv

環境変数など追加

公式サイトのシェル環境を構築する的なところのzshのやり方を実行。

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc

仮想環境の構築

【図解】作業が倍速!pipenvの使い方【Python】

python3.6.13をインストール

pyenv install 3.7.13

chromedriverとrequestsをインストール

インストールさているchromeのヘルプからバージョンを調べる
103.0.5060.114

対応するchromedriverのバージョンを確認。
ドンピシャがなかったので一番数字が大きい103.0.5060.53.0をインストール

ちなみにchromedriverという名前ではなくchromedriver-binaryです。

pipenv install chromedriver-binary==103.0.5060.53.0
pipenv install requests

サンプルプログラム実行

仮想環境に切替

pipenv shell

動作チェックを兼ねたサンプルプログラム

多くの記事が古い関数を使っていたため、そこでトラブった。DOMの要素を取得する関数がdrive.find_element_?????のような形からdriver.find_elementに統一されていた。

from selenium.webdriver.common.by import By
import time
from selenium import webdriver
import chromedriver_binary
 
driver = webdriver.Chrome()
driver.get('https://www.google.co.jp/')
search_box= driver.find_element(By.NAME, "q")
search_box.send_keys("selenium pipenv")
search_box.submit()
time.sleep(5)
driver.quit()

実行

python test.py

ポケモンのスクレイピング(本題)

processingで使ってたのでpythonの情報を漁っても割と理解できた。とりあえずスクレイピングで来たのでめでたしめでたし!

from selenium.webdriver.common.by import By
from selenium import webdriver
import chromedriver_binary
import time
import csv
import json
import requests
import os

driver = webdriver.Chrome()
driver.get('https://zukan.pokemon.co.jp/')

time.sleep(3)

for i in range(1):
    driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
    time.sleep(1)

csv_file_name = "pokemon.csv"
f = open(csv_file_name, "w", encoding="utf_8_sig", errors="ignore")

writer = csv.writer(f, lineterminator="\n") 
csv_header = ["ナンバー", "サブナンバー", "名前", "名前(サブ)", "エリア", "重さ", "高さ", "性別", "分類", "特性1", "特性2", "タイプ1", "タイプ2", "テキスト1", "テキスト2", "テキスト3", "HP", "こうげき", "ぼうぎょ", "とくこう", "とくぼう", "すばやさ", "sugata_text_flg", "sugata_text", "mega_flg", "genshi_flg", "kyodai_flg", "イメージL", "イメージM", "イメージS", "図鑑No."]
writer.writerow(csv_header)

no = 1
for elem_li in driver.find_elements(By.CLASS_NAME, "loadItem"):
    
    img = elem_li.find_element(By.TAG_NAME, "img")
    p = elem_li.find_element(By.TAG_NAME, "p")
    a = elem_li.find_element(By.TAG_NAME, "a")
    
    imgurl = img.get_attribute("src")
    pname = p.text
    jsonurl = a.get_attribute("href")    
    jsonurl = jsonurl.replace("https://zukan.pokemon.co.jp", "")
    jsonurl = "https://zukan.pokemon.co.jp/zukan-api/api{}".format(jsonurl)
    
    # Jsonファイル(ポケモンのステータス)を取得
    responce = requests.get(jsonurl)
    jsondata = json.loads(responce.text)
    
    # 必要なステータスを抜き出す
    sName = jsondata["pokemon"]["name"]
    sOmosa = jsondata["pokemon"]["omosa"]
    sNo = jsondata["pokemon"]["no"]
    sSub = jsondata["pokemon"]["sub"]
#     print("{}の重さは{}です。".format(sName, sOmosa))
    
    # コンソールに表示
    print("{}:{}のダウンロード中".format(no, pname))

    # 画像の取得
    filename = "{}-{}_{}".format(sNo, str(sSub), sName)
    responce = requests.get(imgurl)
    with open("img/" + "{}.png".format(filename), "wb") as f:
        f.write(responce.content)
        
    # 取得データをCSVに出力
    csvlist = []
#     csvlist.append(imgurl)
#     csvlist.append(pname)
#     csvlist.append(jsonurl)
    for myvalue in jsondata["pokemon"].values():
        csvlist.append(myvalue)
    writer.writerow(csvlist)
    
    no += 1

time.sleep(1)
driver.quit()

コメントする