PythonでスクレイピングしてGoogleスプレッドシートにデータをまとめる

この記事を読むのに必要な時間は約 19 分です。

この記事を読むのに必要な時間は約 19 分です。

最近、Aidemyでスクレイピング入門を勉強したのですが、

なかなか面白かったので、自分でもスクレイピング処理を1から作ってみたくなり。。。。

 

実際にWebサイトからデータをスクレイピングして、Googleスプレッドシートにまとめる処理を作成してみました。

 

ということで今回は、スクレイピング処理作成の流れを記事にまとめてみました。

今回やったことをざっくりと絵にすると

 

 

この記事を読む上での前提事項

  • Googleアカウント作成済みであること
  • Colaboratoryが利用可能な状態であること
  • Google Chromeがインストール済みであること

 

MEMO

ColaboratoryとはGoogleの仮想マシン上で動くPython実行環境です。

 

GPUも無料で利用することができるので、

Deep Learningのモデルの学習処理も高速に実施できます。

 

スクレイピング実践練習

 

ブラウザでスクレイピング対象確認

それではスクレイピング処理を実装するまでの流れを説明していきます。

 

まず、今回のスクレイピング対象のデータですが、

あるサイトで管理している食品に含まれる栄養素(たんぱく質、炭水化物、脂質)の量と勝手に設定しています。

 

まずは、Google Chromeを開いてブラウザ上で収集したいデータを確認します。

 

 

サイドバーに食品や料理のカテゴリリンクがあり、

カテゴリリンクを選択すると食品一覧が並びます。食品の一覧はそれぞれが詳細画面へのリンクになっています。

 

 

あるカテゴリの食品が、50件より多い場合はページングされます。

 

 

各食品の詳細画面には収集したい食品の栄養素(たんぱく質、脂質、炭水化物)があります。

このデータが今回のスクレイピング対象です。

 

 

Chrome Developer Toolでスクレイピング対象のHTML要素確認

先ほどブラウザで確認した画面において、

今度はChrome Developer Toolを利用してHTML要素を確認します。

 

MEMO

Chrome Developer Toolとは、

Google Chrome に組み込まれたツールのことです。

 

HTML要素が検証できたり、デザインをブラウザ上で修正して確認できたり、

ブラウザ上で動くフロントエンドの処理をデバッグできたりします。

 

Windowでは「F12」、Macでは「command」「option」「i」で起動できます。

(ブラウザ上で右クリック>検証でも起動可能)

 

 

それでは、Developer Toolを起動してHTML要素を確認します。

まずはサイドバーについてHTML要素を確認してみましょう。

 

 

Developer Toolの矢印マークをクリックして調べたい要素にカーソルを合わせます。

上の例ではサイドバーの主食のリンクにカーソルを合わせていますが、

左の画面上フォーカスを当てると右のDeveloper Toolでそれに対応する要素が確認できます。

 

サイドバーのリンク一覧を取得したい場合は、「aタグのhref属性にcategoryほにゃらら」というような条件で抜き出せそうです。

 

 

次は、ページングリンクについて確認します。

 

 

1つのカテゴリの食品が50以上ある場合はページングされるので、ページングリンク全てを取得する必要があります。

色々やり方はありそうですが、Lastリンクが使えそうです。

 

Lastリンクの最後のスラッシュ以降の数字を取り出し、

1からLastリンクの数字をリンクとして生成できそうです。

(上の例だと、Lastリンクが/category/16/15なので、/category/16/1〜/category/16/15がリンクになります。)

 

 

次は、一覧画面から詳細画面へのリンクについて確認します。

 

 

classにsoshoku_aが付いているaタグを指定すれば良さそうです。

(このサイトでは他の詳細画面へのリンクにも同じようにsoshoku_aが付いていました)

 

最後は、詳細画面に表示されている栄養素のHTML要素を確認します。

 

 

たんぱく質にはidにprotein_content、脂質にはidにfat_content、炭水化物にはidにcarb_content

がそれぞれ指定されていることが分かります。

 

ここまでで、各画面でどのタグをどのように指定すればHTML要素を取得できるかが確認できました。

 

クレイピング処理をブラウザで再現

クレイピングのプログラミングの前に、

クレイピングの処理の流れをブラウザで画面を動かして確認しておきます。

 

今回は、サイトのTOP画面サイドバーの主食のリンク先からスタートすることとします。

 

主食のリンクをクリックすると主食の一覧が表示されます。

ページングされているのでページングリンク全て取得します。

 

 

次は各ページリンクにおいて、一覧表示されている詳細画面へのリンクを全て取得します。

 

 

最後に各詳細画面において、栄養素を取得します。

 

 

以上が、今回作るスクレイピング処理の流れです。

 

クレイピング処理作成

それでは、スクレイピング処理を作成します。

作成したプログラムは以下です。

 

Python
from bs4 import  BeautifulSoup
from google.colab import auth
from oauth2client.client import GoogleCredentials
import gspread
import requests
# URL
authority = "https://・・・/"



# 指定されたセレクタとURLを元にリンクを取得する
def getUrls(selector, url):
  url_list = []
  r = requests.get(url)
  soup = BeautifulSoup(r.text, "lxml")
  urls = soup.select(selector)
  
  for url in urls:
    url = authority + url.get("href")
    url_list.append(url)
  
  return url_list


# 指定されたセレクタとURLを元にページングリンクを取得する
def getPages(selector, url):
  url_list = []
  r = requests.get(url)
  soup = BeautifulSoup(r.text, "lxml")
  urls = soup.select(selector)
  
  for url in urls:
    page = url.text
    
    if page == "Last":
      lastUrl = url.get("href")
      lastNumber = int(lastUrl.split("/")[-1])
      baseUrl = "/".join(lastUrl.split("/")[0:-1])
      
      for i in range(lastNumber):
        pagesUrl = authority + baseUrl + "/" + str(i+1)
        url_list.append(pagesUrl)

  return url_list


# 指定されたURLを元に食品名称、タンパク質、脂質、炭水化物を取得する
def getFoodAttribute(food_url):
  foodDictionary = {}
  r = requests.get(food_url)
  soup = BeautifulSoup(r.text, "lxml")
  # 食品名称
  name = soup.select('h1[class*="ccdsSingleHl01"]')
  if len(name) > 0:
    foodDictionary["name"] = name[0].text
  else:
    foodDictionary["name"] = ""
  # タンパク質
  protein = soup.select('span[id*="protein_content"]')
  if len(protein):
    foodDictionary["protein"] = protein[0].text
  else:
    foodDictionary["protein"] = ""
  # 脂質
  fat = soup.select('span[id*="fat_content"]')
  if len(fat):
    foodDictionary["fat"] = fat[0].text
  else:
    foodDictionary["fat"] = ""
  # 炭水化物
  carb = soup.select('span[id*="carb_content"]')
  if len(carb):
    foodDictionary["carb"] = carb[0].text
  else:
    foodDictionary["carb"] = ""
  
  return foodDictionary


# 指定された食品情報をスプレッドシートに書きこむ
def insertSpread(foodDictionaryList):
  # 認証処理
  auth.authenticate_user()
  gc = gspread.authorize(GoogleCredentials.get_application_default())
  
  # 指定のスプレッドシートの先頭ワークシートをオープン
  worksheet = gc.open_by_key('1W5nH2・・・').get_worksheet(0)
  
  for food in foodDictionaryList:
    registData = []
    registData.append(food.get("name"))
    registData.append(food.get("protein"))
    registData.append(food.get("fat"))
    registData.append(food.get("carb"))
    worksheet.append_row(registData)
    

#**********メイン処理**********

# ページングのリンクを取得する
paging_url_list = getPages('a[href*="category"]', "https://・・・/category/17/")


# 食材のリンクを取得する
food_url_list = []
for url in paging_url_list:
  food_url = getUrls('a[class*="soshoku_a"]', url)
  food_url_list.append(food_url)


# 各食材のたんぱく質、脂質、炭水化物を取得する
food_attribute_list = []
for food_url in food_url_list:
  for url in food_url:
    food_attribute = getFoodAttribute(url)
    food_attribute_list.append(food_attribute)


# スプレッドシートに書き込む
insertSpread(food_attribute_list)

 

プログラム解説

まず、関数について解説します。

getUrls

URLとセレクタを指定すると、

URLで指定したページのセレクタを対象としてhref属性の値(リンク)の一覧を作成して返却する関数です。

 

例えばセレクタにa[class*=category]を指定すると、

aタグのclass属性にcategoryという文字列を含むHTML要素のhref属性の値が取得できます。

 

この関数ではまず、request.get(url)で全てのhtml要素を取得し、

BeautifulSoupを使ってsoup.select(selector)でセレクタで指定した要素のみを取得しています。

 

 

getPages

URLとセレクタを指定すると、

指定したURLのページングのリンクを全て取得して返却する関数です。

 

ページングのLastの数字を取得して1からその数字までのリンクを作成して返却する関数です。

(パッと思いついたのがこのやり方でしたが、他にいいやり方がありそうです。。。)

 

 

getFoodAttribute

指定された詳細画面のURLを元に、

たんぱく質、脂質、炭水化物、(食品名)を取得し、値をディクショナリにセットして返却する関数です。

 

(このサイトでしか通用しないスクレイピングの作り方です。。改善の余地ありです、、、)

 

 

insertSpread

この処理はおまけですが、、

栄養素の情報をスプレッドシートに書き込む関数です。

 

 

最後にメイン処理についてですが、処理の流れは以下です。

  1. TOPのサイドバーの主食カテゴリーリンク先のページングリンクの一覧を取得します。
  2. 各ページングリンク先の主食一覧画面から詳細画面へのリンクを取得します。
  3. 各詳細画面リンク先のたんぱく質、脂質、炭水化物、(食品名)の値を取得します。
  4. 取得した栄養素の情報をスプレッドシートに書き込みます。

 

おわりに

 

今回は実際のWebサイトからスクレイピングする練習をしました。

 

応用すれば、

画像データをネット上からかき集めて、簡単に機械学習モデルのトレーニングデータが用意できたりと、

スクレイピング活用例を色々調べてみると面白いネタが見つかりそうでうす。

 

 

ただ、今回は静的コンテンツのスクレイピングだったので簡単でしたが、

動的コンテンツになると認証を通したりと、ハードルが少し高くなります。。。

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください