PythonでWebスクレイピングを実践|初心者向けに商品情報を取得してCSVに保存

Pythonを使うと、Webページに掲載されている情報を自動で取得できます。

前回の記事では、requestsとBeautiful Soupを使ったWebスクレイピングの基本を紹介しました。

今回はさらに一歩進んで、実際にWebページから商品情報を取得して、CSVファイルに保存するプログラムを作ってみましょう。

今回使用するのは、Webスクレイピングの練習用に用意された「Books to Scrape」というWebサイトです。

この記事では、

  • Webページから商品情報を取得する
  • HTMLの構造を確認する
  • 商品名・価格・評価を取得する
  • 複数の商品をまとめて取得する
  • 商品ページのURLを取得する
  • 取得した情報をCSVファイルに保存する

という流れを、Python初心者向けにやさしく解説します。


Webスクレイピングを実践してみよう

Webスクレイピングでは、Webページから必要な情報をプログラムで取得します。

例えば、人間がWebページを見ながら、

商品名を確認
↓
価格を確認
↓
評価を確認
↓
URLをコピー
↓
ExcelやCSVに貼り付ける

という作業をしているとします。

これをPythonにやってもらうイメージです。

Webページ
    ↓
Pythonで取得
    ↓
HTMLを解析
    ↓
必要な情報を取り出す
    ↓
CSVに保存

今回は架空の書店サイトから、本の商品情報を取得してみます。


今回使用する「Books to Scrape」

今回の練習では、Books to ScrapeというWebサイトを使用します。

Books to Scrapeは、Webスクレイピングの練習用に作られた架空のオンライン書店です。

Webページには、本の商品情報として、

  • タイトル
  • 価格
  • 在庫状況
  • 評価
  • 商品ページへのリンク

などが掲載されています。

実際のショッピングサイトを教材にすると、利用規約やアクセス制限などを確認する必要があります。

そのため、この記事ではスクレイピングの練習用サイトを使います。


今回作るプログラム

今回の目標は、Webページから本の情報を取得してCSVファイルに保存することです。

最終的には、

Webページ
 ↓
requests
 ↓
Beautiful Soup
 ↓
商品情報を取得
 ↓
CSVファイルに保存

というプログラムを作ります。

CSVファイルには、例えば次のような情報を保存します。

タイトル,価格,評価,URL
A Light in the Attic,£51.77,Three,...
Tipping the Velvet,£53.74,One,...
Soumission,£50.10,One,...

では、順番に作っていきましょう。


必要なライブラリをインストールする

まず、Webスクレイピングに必要なライブラリをインストールします。

今回使用するのは、

  • requests
  • Beautiful Soup

です。

コマンドプロンプトやターミナルで、次のコマンドを実行してください。

pip install requests beautifulsoup4

環境によってpipが使えない場合は、

python -m pip install requests beautifulsoup4

でもインストールできます。

Windowsでは、

py -m pip install requests beautifulsoup4

という方法もあります。

CSVファイルの作成には、Pythonに標準で搭載されているcsvモジュールを使用するため、追加インストールは必要ありません。


Books to ScrapeのWebページを取得する

まずは、Books to ScrapeのWebページをPythonで取得してみましょう。

import requests

url = "https://books.toscrape.com/"

response = requests.get(url)

print(response.status_code)

実行して、

200

と表示されれば、Webページを正常に取得できています。

200は、HTTP通信においてリクエストが正常に処理されたことを示すステータスコードです。


Beautiful SoupでHTMLを解析する

次に、取得したHTMLをBeautiful Soupで解析します。

import requests
from bs4 import BeautifulSoup

url = "https://books.toscrape.com/"

response = requests.get(url)

soup = BeautifulSoup(response.text, "html.parser")

ここでは、

response.text

にWebページのHTMLが入っています。

それを、

BeautifulSoup(response.text, "html.parser")

に渡すことで、HTMLの構造をPythonから扱いやすくします。


WebページのHTML構造を確認する

Webスクレイピングでは、いきなりPythonのコードを書くのではなく、取得したい情報がHTMLのどこにあるのかを確認することが重要です。

Webブラウザには、ページのHTMLを確認するための「開発者ツール」が用意されています。

Webページ上で右クリックして「検証」などを選択すると、HTMLの構造を確認できます。

Books to Scrapeの商品情報を見ると、本はHTMLのarticle要素などで構成されています。

例えば、イメージとして、

<article>
    <h3>
        <a href="...">本のタイトル</a>
    </h3>

    <p class="price_color">£51.77</p>

    <p class="star-rating Three">
        ...
    </p>
</article>

のような構造になっています。

このHTML構造を利用して、必要な情報を取り出します。


まずは1冊分の商品情報を取得する

最初からすべての商品を取得すると分かりにくいので、まずは1冊だけ取得してみましょう。

book = soup.find("article")

find()を使うことで、HTMLの中から最初のarticle要素を取得できます。

次に、本のタイトルを取得します。

title = book.h3.a["title"]

print(title)

これで、本のタイトルを取得できます。


["title"]とは?

ここで少しだけHTMLの属性について説明します。

HTMLでは、

<a title="A Light in the Attic">

のように、タグに属性が設定されていることがあります。

Beautiful Soupでは、

element["title"]

のように書くことで、title属性の値を取得できます。

同じように、

element["href"]

なら、リンク先を表すhref属性を取得できます。


本の価格を取得する

次に、本の価格を取得してみます。

price = book.find("p", class_="price_color")

print(price.text)

これで価格を取得できます。

例えば、

£51.77

のような値が表示されます。

ここで、

class_="price_color"

としていることに注目してください。

HTMLのclass属性を指定するとき、Beautiful SoupではPythonの予約語との衝突を避けるため、class_と書きます。

通貨記号が文字化けする場合

価格の表示が

£51.77

ではなく、

£51.77

のように表示されることがあります。

これは文字コードが合っていないのが原因です。

直すには、

response = requests.get(url)

の後に、

response.encoding = “utf-8”

を入れて、

response = requests.get(url)
response.encoding = “utf-8”

のように記述してください。

これで正しく表示されます。


本の評価を取得する

次は、本の評価を取得してみましょう。

Books to Scrapeでは、評価がHTMLのclass属性で表現されています。

例えば、

<p class="star-rating Three">

のようなHTMLになっています。

Beautiful Soupで取得してみましょう。

rating = book.find("p", class_="star-rating")

print(rating.get("class"))

すると、

['star-rating', 'Three']

のようなリストが取得できます。

このうち、2番目の要素が評価を表しています。

rating = book.find("p", class_="star-rating").get("class")[1]

print(rating)

これで、

Three

のような評価を取得できます。


1冊分の情報をまとめて取得する

ここまでの処理をまとめてみましょう。

import requests
from bs4 import BeautifulSoup

url = "https://books.toscrape.com/"

response = requests.get(url)

soup = BeautifulSoup(response.text, "html.parser")

book = soup.find("article")

title = book.h3.a["title"]
price = book.find("p", class_="price_color").text
rating = book.find("p", class_="star-rating").get("class")[1]

print("タイトル:", title)
print("価格:", price)
print("評価:", rating)

これで、Webページから1冊分の商品情報を取得できました。


Webページ内のすべての本を取得する

ここから、Webスクレイピングらしい処理になってきます。

Books to Scrapeには、1ページに複数の本が掲載されています。

すべての本を取得するには、find_all()を使います。

books = soup.find_all("article")

これで、ページ内にあるarticle要素をまとめて取得できます。

あとはfor文を使って、1冊ずつ処理します。

for book in books:
    title = book.h3.a["title"]
    price = book.find("p", class_="price_color").text
    rating = book.find("p", class_="star-rating").get("class")[1]

    print("タイトル:", title)
    print("価格:", price)
    print("評価:", rating)
    print()

これで、ページ内に掲載されている本の情報を順番に取得できます。


for文で繰り返し処理する

今回の処理では、for文が重要な役割をしています。

for book in books:

というコードによって、

1冊目を処理
↓
2冊目を処理
↓
3冊目を処理
↓
4冊目を処理
↓
...

という処理を自動的に繰り返します。

人間が1冊ずつ確認してコピーする必要はありません。

これこそが、Webスクレイピングの便利なところです。


商品ページのURLも取得する

次に、それぞれの本の商品ページのURLも取得してみましょう。

本のタイトルが入っているaタグには、href属性があります。

href = book.h3.a.get("href")

print(href)

すると、

catalogue/a-light-in-the-attic_1000/index.html

のようなURLが取得できます。

ただし、これは「相対URL」と呼ばれる形式です。


相対URLを完全なURLに変換する

例えば、

catalogue/a-light-in-the-attic_1000/index.html

というURLがあった場合、

https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html

という完全なURLに変換したいことがあります。

この処理には、Python標準ライブラリのurllib.parseにあるurljoin()を使えます。

from urllib.parse import urljoin

book_url = urljoin(url, book.h3.a.get("href"))

print(book_url)

これで、完全なURLを作成できます。


CSVファイルに保存する

ここまで取得できた情報を、CSVファイルに保存してみましょう。

Pythonには、CSVファイルを扱うためのcsvモジュールが標準で用意されています。

まず、

import csv

を追加します。

そして、CSVファイルを開きます。

with open("books.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)

これで、books.csvというファイルにデータを書き込む準備ができます。


CSVに見出しを書き込む

最初に、CSVファイルの見出しを書き込みます。

writer.writerow(["タイトル", "価格", "評価", "URL"])

CSVファイルには、

タイトル,価格,評価,URL

という見出しが入ります。


商品情報をCSVに書き込む

次に、先ほどのfor文を組み合わせます。

with open("books.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)

    writer.writerow(["タイトル", "価格", "評価", "URL"])

    for book in books:
        title = book.h3.a["title"]
        price = book.find("p", class_="price_color").text
        rating = book.find("p", class_="star-rating").get("class")[1]
        book_url = urljoin(url, book.h3.a.get("href"))

        writer.writerow([title, price, rating, book_url])

これで、Webページから取得した情報をCSVファイルに保存できます。


完成したプログラム

ここまでの処理を、一つのプログラムにまとめてみましょう。

import csv
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

url = "https://books.toscrape.com/"

response = requests.get(url)
response.raise_for_status()

soup = BeautifulSoup(response.text, "html.parser")

books = soup.find_all("article")

with open("books.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)

    writer.writerow(["タイトル", "価格", "評価", "URL"])

    for book in books:
        title = book.h3.a["title"]
        price = book.find("p", class_="price_color").text
        rating = book.find("p", class_="star-rating").get("class")[1]
        book_url = urljoin(url, book.h3.a.get("href"))

        writer.writerow([title, price, rating, book_url])

print("CSVファイルを作成しました!")

実行すると、Pythonプログラムを実行したフォルダーに、

books.csv

というCSVファイルが作成されます。


作成されたCSVファイルを確認する

作成されたCSVファイルをExcelなどで開いてみましょう。

例えば、

タイトル                  価格       評価    URL
A Light in the Attic      £51.77    Three   ...
Tipping the Velvet       £53.74    One     ...
Soumission               £50.10    One     ...
...

のように、Webページに掲載されていた情報が表形式で整理されています。

Webブラウザで人間が1冊ずつ情報をコピーする代わりに、Pythonが自動的に収集してくれました。


response.raise_for_status()とは?

完成したプログラムには、次のコードを追加しています。

response.raise_for_status()

これは、Webページの取得に失敗した場合などに、エラーを発生させるためのものです。

例えば、URLが間違っていたり、サーバーからエラーが返されたりした場合に、そのまま処理を続けるのではなく、問題が発生したことを知らせてくれます。

スクレイピングのプログラムでは、こうしたエラー処理を入れておくと、問題が起きたときに原因を確認しやすくなります。


WebスクレイピングではHTMLの構造を確認することが重要

今回のプログラムでは、

book.h3.a["title"]

や、

book.find("p", class_="price_color")

などを使いました。

これらは、Books to ScrapeのHTML構造を確認したうえで指定しています。

つまり、Webスクレイピングでは、

Webページを見る
↓
HTMLの構造を確認する
↓
必要な情報がどこにあるか探す
↓
Beautiful Soupで取得する

という作業が重要になります。

WebサイトのHTML構造が変更されると、以前は動いていたスクレイピングプログラムが動かなくなることもあります。


Webスクレイピングではサイトのルールを確認する

Webスクレイピングは便利ですが、どのWebサイトでも自由に情報を取得してよいわけではありません。

実際のWebサイトをスクレイピングするときは、事前に、

  • 利用規約
  • robots.txt
  • APIの有無
  • サーバーへの負荷
  • 著作権
  • 個人情報

などを確認する必要があります。

特に、短時間に大量のアクセスを繰り返すようなプログラムは、Webサーバーに負荷をかける可能性があります。

また、スクレイピングできる技術があることと、そのサイトから自由に情報を取得してよいことは別です。

公式APIが提供されている場合は、スクレイピングではなくAPIを利用する方法も検討しましょう。

今回の記事では、スクレイピングの学習用に用意されたWebサイトを利用しています。


今回のプログラムで学んだこと

今回は、実際にWebスクレイピングのプログラムを作りました。

覚えておきたいポイントを整理しましょう。

  • requestsでWebページを取得できる
  • Beautiful SoupでHTMLを解析できる
  • find()でHTML要素を取得できる
  • find_all()で複数の要素を取得できる
  • HTMLの属性から情報を取得できる
  • for文を使って複数の商品を処理できる
  • urljoin()で相対URLを完全なURLに変換できる
  • csvモジュールで取得した情報をCSVに保存できる
  • Webスクレイピングでは対象サイトのルールを確認することが重要

今回のプログラムでは、Webページに掲載された情報を、

Webページ
 ↓
requests
 ↓
Beautiful Soup
 ↓
必要な情報を抽出
 ↓
CSV

という流れでデータ化しました。


まとめ

今回作ったプログラムは、本の情報を取得するだけのものです。

しかし、考え方を応用すれば、さまざまな情報収集を自動化できます。

例えば、

  • Webページのタイトルを取得する
  • ニュース記事の情報を取得する
  • 複数ページの情報をまとめる
  • Web上の情報をCSVに保存する
  • 取得したデータをExcelで整理する
  • 定期的にWebページを確認する

といった処理です。

つまりWebスクレイピングは、単に「Webページから情報をコピーする技術」ではありません。

人間が繰り返している情報収集作業をPythonで自動化するための技術として考えると、より実用的になります。

関連記事
・PythonでWebスクレイピングをする方法|初心者向けにWebページの情報を取得
・PythonでCSVファイルを扱う方法|初心者向けに読み込み・書き込みをやさしく解説
・WindowsにPythonをインストールする方法【初心者向け】


タイトルとURLをコピーしました