1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Python 初学者が楽天APIを使って買い物リスト作成アプリを作った(データ収集編:3)

Last updated at Posted at 2023-02-10

この記事は以下の続きです

今回は、こちらの表のURLを使って各レシピの材料と量を取得していきます。
image.png

作りたい表はこちら(どのようなデータ型にしたいか考えるの大切!)
二つの表のindexは対応しています。
image.png

買い物リスト作成アプリの概要はこちら

★このページは以下項目で構成されています★

項番 ページ内リンク
1 準備
2 Excel操作
3 楽天レシピサイトから材料と量を見つける
4 Excelに書き込む
5 コード全文

準備

今回のスクレイピングで使うSeleniumとは、ブラウザを自動的に操作するライブラリです。
requestsライブラリを利用して、WEBサイトからデータを自動的に取得することができます。

そのために、以下が必要です。
・webブラウザ (Google Chrome やFirefoxなど)
・WebDriver (ブラウザの操作を自動化する)
・selenium

WebDriver準備

Google Chromeを使っていましたので、ChromeDriverのインストールを行います。
注意点としては、Chromeのバージョンと合っているChromeDriverをインストールしないといけません。

私は、なぜかバージョンを合わせてインストールしたのに、プログラム動かしたときに動かなくて、動かせるようになるまで半日かかりました・・・。
最終的に、webdriver_managerというライブラリを使用し、ブラウザのバージョンアップを自動化することで解決しました。
まず、コマンドプロンプトなどでwebdriver_managerをインストールします。

pip3 install webdriver-manager

そして、VScodeなどでこちらをインポート

Python
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

こちらでブラウザ起動が自動でできます。

Python
new_driver = ChromeDriverManager().install()
service = ChromeService(executable_path=new_driver)
browser = webdriver.Chrome(service=service, options=options)

参考文献はこちら

selenium インストール

これをコマンドプロンプトなどで入力。

pip install selenium==4.4.3

そして、VScodeなどでこちらをインポート。
今回は大量のサイトに自動アクセスするのでサーバーに負荷をかけないように「time」モジュールもインポートします。
ついでにExcelも使うので 「openpyxl」インポート。

Python
from selenium import webdriver
import time
import openpyxl
from selenium.webdriver.common.by import By #find_elementsメソッドを使うために用意

これで準備が整いました。次は、Excelを操作していきます。

Excel操作

まず、データを入れるExcelファイルを用意しておきます。
ファイルのA列に index、B列に材料、C列に量のデータを入れたいので、それぞれ1行目に名前を入れておきます。

Python
wb_new = openpyxl.Workbook() #真っ白なExcelファイル作成
ws_new = wb_new.active #シートを選択 active(今触っている)なシートを指定
ws_new.title = "材料データ" #シートにタイトルつける
ws_new['A1'].value = 'index' 
ws_new['B1'].value = '材料'
ws_new['C1'].value = ''

次は、URLが沢山載っているExcelファイルから、indexとURLのリストを作ります。

これは、毎回Excelを読み込んで・・・上から順番にURLにアクセスして・・・情報を取って・・・としていると時間がかかるので、時短のためにリストを作っておきます。

Python
#材料と量を取りたいExcelを読み込む
file = "recipe_all"
wb_read = openpyxl.load_workbook(file + ".xlsx")

#先頭のシートを取得(先頭のインデックス番号は0)
ws_read = wb_read.worksheets[0] #先ほどの「Excelファイル.active」でも良い

#idとurlのリストを作る
id_url_lists=[]
for id_rows,url_rows in zip(ws_read.iter_rows(min_row=2, min_col=1, max_col=1), ws_read.iter_rows(min_row=2, min_col=3, max_col=3)):       
    id_url=[]
    for id_row,url_row in zip(id_rows,url_rows):        
      id_url.append(id_row.value)#リストにセルのデータを追加
      id_url.append(url_row.value)
    id_url_lists.append(id_url)#さらにid_url_listに格納

実行するとこんな感じでidとURLが行ごとにセットになって、2重配列となります。
image.png

楽天レシピサイトから材料と量を見つける

先ほどのidとURLのリストのはじめから順番にアクセスしていきます。

Python
#ver.を合わせたwebdriverをダウンロードしてChromeブラウザを開く
browser = webdriver.Chrome(ChromeDriverManager().install()) 
#urlリストから順番にアクセス
for id_url_list in id_url_lists:
    browser.get(id_url_list[1])   #driver.get(URL)でそのURLにアクセスできます。
    time.sleep(3)  #サーバーに負担をかけないように3秒待つ

さて、楽天レシピのページに自動でアクセスできるようになりました。

ここから欲しい情報は、材料と量の情報です。
image.png
楽天レシピサイトでは、このように1列に材料と量が格納されており、複数の列で構成されています。

seleniumを使っての要素の検索方法は複数あります。
idやclassなどタグの属性を検索したり、XPathというHTMLの要素を特定する記法も使えます。
一つの要素だけ検索するのであればfind_elementメソッド、複数の要素であればfind_elementsメソッドを使います。

今回は、複数の要素が必要なのでfind_elementsを使います。

レシピページで要素の検証を行うと、
image.png
材料と量の列は「recipe_material_item」というclassネームで構成されていることが分かります。

Python
#材料と量を見つける
recipe_materials = browser.find_elements(By.CLASS_NAME, "recipe_material__item")

こちらで1列分の情報が取れます。
これだけでは
image.png
このようにわけがわからないので、.text を付けると

Python
print(recipe_material.text)

結果
image.png
このように材料と量が、改行されて取得できます。
さらに改行で分割すると

Python
recipe_material = recipe_material.text.splitlines() #改行コード[\nで材料と量が分割されているのでsplitlinesで分割
print(recipe_material)

このように材料と量のリストで返されます。
image.png

Excelに書き込む

取得した情報をどうやってExcelに書き込むかというところですが、
appendメソッドでリストをExcelに書き込めるようなので、
[index, 材料, 量] の形を作って1行ずつExcelに書き込んでいくことにします。

さらに、楽天レシピは材料記載はありますが、量の記載がないことがあるので、if文で量が無い時は「none」と入力することにしました。

Python
for recipe_material in recipe_materials:
    
    recipe_material = recipe_material.text.splitlines() #改行コード[\nで材料と量が分割されているのでsplitlinesで分割
    
    list=[]
    list.append(id_url_list[0])#listにid入れる
    if len(recipe_material) == 2 :
      list.append(recipe_material[0]) #recipe_material[0]は材料 
      list.append(recipe_material[1]) #recipe_material[1]は量    
    else:
      list.append(recipe_material[0])
      list.append("none")
    ws_new.append(list)
    wb_new.save(file + "test.xlsx") #1行書き込んでsaveした方が時間短縮できたのでそうしています

これで
image.png
この表ができるわけですが、材料列に★や☆など記号が含まれたりしているので、次でデータ加工していきます。

コード全文

Python
import openpyxl
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service as ChromeService
import time
from selenium.webdriver.common.by import By
#from selenium.webdriver.common.keys import Keys

#材料と量を入れるexcelファイルをあらかじめ用意しておく
wb_new = openpyxl.Workbook()
ws_new = wb_new.active
ws_new.title = "材料データ"
ws_new['A1'].value = 'index'
ws_new['B1'].value = '材料'
ws_new['C1'].value = ''

#材料と量を取りたいExcelを読み込む
file = "recipe_index"
wb_read = openpyxl.load_workbook(file + ".xlsx")

#先頭のシートを取得(先頭のインデックス番号は0)
ws_read = wb_read.worksheets[0]

#---------------------IDと一緒にURLリストをつくる。----------------------
id_url_lists=[]
for id_rows,url_rows in zip(ws_read.iter_rows(min_row=2, min_col=1, max_col=1), ws_read.iter_rows(min_row=2, min_col=3, max_col=3)):       
  id_url=[]
  for id_row,url_row in zip(id_rows,url_rows):        
    id_url.append(id_row.value)#リストにセルのデータを追加
    id_url.append(url_row.value)
  id_url_lists.append(id_url)#さらにid_url_listに格納

print(id_url_lists)

#---------------------------------seleniumでスクレイピングしていく-----------------------
#ver.を合わせたchromeドライバーをダウンロードしてChromeブラウザを開く
new_driver = ChromeDriverManager().install()
service = ChromeService(executable_path=new_driver)
browser = webdriver.Chrome(service=service)

#urlリストから順番にアクセスして材料と量を取得
for id_url_list in id_url_lists:

  browser.get(id_url_list[1])   
  time.sleep(3)    
      
  #材料名を見つける
  recipe_materials = browser.find_elements(By.CLASS_NAME, "recipe_material__item")
 
  #材料名をfor文で取得する
  for recipe_material in recipe_materials:
    
    recipe_material = recipe_material.text.splitlines() #改行コード[\nで材料と量が分割されているのでsplitlinesで分割
    
    list=[]
    list.append(id_url_list[0]) #listにid入れる
    if len(recipe_material) == 2 :
      list.append(recipe_material[0]) #recipe_material[0]は材料
      list.append(recipe_material[1]) ##recipe_material[0]は量    
    else:
      list.append(recipe_material[0])
      list.append("none")
    ws_new.append(list)
    wb_new.save(file + "test.xlsx")
  print(id_url_list)

browser.quit()

次回からデータ加工編に行きます!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?