Python + BeautifulSoup4でWebサイトをスクレイピング

2019年4月9日火曜日

BeautifulSoup Python スクレイピング

t f B! P L

Python + BeautifulSoup4でWebサイトをスクレイピング

この記事では、Python+BeautifulSoupでWebスクレイピングする方法を紹介します。

HTMLコードのイメージ

インストール

前準備として「Requests」と「BeautifulSoup」をpipでインストールします。

pip install requests
pip install beautifulsoup4

注意事項

Pythonに限らず、Webスクレイピングでは、ルールを守ってスクレイピングしないと、法的に訴えられる事もあるので、ルールを守って開発しましょう。

# スクレイピング、クローリングする時の注意点
岡崎市立中央図書館事件(Librahack事件) - Wikipedia

サンプルコード

以下のサンプルHTMLから、今日の日経平均を取得するのPythonのコードです。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>ページタイトル</title>
</head>
<body>
  <div class="today">
    <h1>今日の日経平均は</h1>
    <p>10,000円</p>
  </div>
  <div class="yesterday">
    <h1>昨日の日経平均は</h1>
    <p>9,000円</p>
  </div>
</body>

[Python]

import requests
from bs4 import BeautifulSoup

#スクレイピング対象のURL (今回はローカルサーバのHTMLファイルを対象にする)
target_url = "http://127.0.0.1/sample.html"

#requestsを使って、GETリクエストを送信
r = requests.get(target_url)
#レスポンスのHTMLを解析
soup = BeautifulSoup(r.text, 'html.parser') 

#今日の日経平均が格納されているタグを抽出する (div.today > p)
div = soup.find('div', class_="today")
p = div.find("p")
print(p.string)  #=> 10,000円

BeautifulSoupのいろいろな使い方

Python+BeautifulSoupで、Webスクレイピングするときによく使う関数を紹介します。

一致するタグをすべて抽出

for a in soup.find_all("a"):
  print(a.get("href"))

見つかった最初のタグを抽出

soup.find("a")

抽出したタグから値を取得する

  • 属性値の取得
soup.find("a").get("href")
  • タグの中の文字列を取得
soup.find("a").string

タグを抽出する条件を指定する

soup.find("a", class_="classname", href="/page1.html")

※classなどのPythonの予約語を条件を指定する場合は、後ろにアンダーバーが必要です。

以下の書き方でもOK

soup.find_all("a", attrs={"class": "classname", "href": "page1.html"})

正規表現を使ったタグの抽出

  • hから始まるタグを抽出(h1〜h6)
import re
soup.find_all(re.compile("^h"))
  • 拡張子.jpgにリンクしているタグを抽出
soup.find_all(href=re.compile("\\.jpg$"))
  • タグの中の文字列を正規表現で検索
soup.find_all(text=re.compile("Python"))

タグ(要素)名の取得

soup.find(class_="classname").name

CSSセレクタを使ってタグを抽出

CSSセレクタを使ってタグを検索することもできます。CSSセレクタを使うと、かなり柔軟な検索処理が行え、さらにPythonのコードもスッキリします。

classセレクタ

soup.select(".myclass")

# クラス名をAND条件で検索
soup.select(".car.prius")

IDセレクタ

soup.select("#myid")

要素セレクタ

soup.select("a")

属性セレクタ

# href属性を持つ aタグを抽出
soup.select('a[href]')

# 完全一致
soup.select('a[href="page1.html"]')

# 先頭が一致
soup.select('a[href^="http://example.com/"]')

# 末尾が一致
soup.select('a[href$=".jpg"]')

# 部分一致
soup.select('a[href*="hello"]')

タグの親子関係を指定するセレクタ

# 子孫セレクタ (p配下のaタグがすべて抽出される)
soup.select("p a")

# 親子セレクタ (p直下のaタグが抽出される)
soup.select("p > a")

# 隣接セレクタ (pタグ直後に隣接しているaタグが抽出される)
soup.select("p + a")

複数のセレクタをOR条件で指定

複数のセレクタを指定するには、カンマ区切りで記述する。
この時、いずれかのセレクタに一致した場合にタグが抽出される。(OR条件)

# jpg,pngにリンクしているaタグを抽出
soup.select('a[href$=".jpg"], a[href$=".png"]')

CSSセレクタで見つかった先頭1見目のタグを抽出(select_one)

CSSセレクタで見つかった最初の1件を返す方法です。select_oneはCSSセレクタで指定した条件にヒットするタグが、1つだけと分かっている場合や、複数一致した中の先頭1件を取得した場合などに使用します。

soup.select_one("#myid")

指定要素の子孫タグを含めたすべてのテキスト取得する方法

BeautifulSoupの.stringは、以下のようなネストしたタグ構造の場合、うまくテキストを取得できません。

<div class="parent">
  <p>テキスト</p>
  <div>
    <span>テキスト</span>
  </div>
</div>

上記のようなネストしたタグから、一括してテキストを取得する場合は、以下のように書きます。

  children = soup.find("div", class_="parent").find_all()
  text_list = []
  for child in children:
    text_list.append(child.string or "")
  return "".join(text_list)

まとめ

Python+BeautifulSoupで、Webスクレイピングを行う方法を紹介してきました。正規表現や、CSSセレクタをマスターすれば、自由に欲しい情報が手に入ると思います。ルールを守ってスクレイピングを楽しみましょう。

この記事以外にも、PythonでWebスクレイピングを行う方法を紹介しているサイトは沢山あります。Webスクレイピングを始めるならPythonがおすすめです!

関連記事

MacにPython3をインストールする! (サクッとインストールしたい人向け)

Mac環境に、Python3を簡単にインストールする方法を紹介しています。

Python3入門! 基礎をおさらい (変数/演算子/条件分岐/繰り返し)

1つの記事に、基本文法をまとめて書いているので、時間が空いて忘れてしまった場合でも、一気に復習出来るようになっています。よければ見てください。

Flaskでソースの変更を検知して、Webアプリを自動リロードする[Python Tips]

Flaskの開発で、ソースを更新したら、自動的にWebアプリをリロードする方法です。

Flaskで REST API開発する! 直ぐに実行できるサンプルコードで解説 【Python Tips】

Pythonの軽量Webフレームワークである、FlaskでREST APIを作るまでの流れを、紹介します。

Flask-RESTful を使って、REST APIを作る【Python Tips】

Flaskと、Flask-RESTfulを使って、REST APIを作ります。
Flask-RESTfulを使うと、オブジェクト思考な感じで、REST APIが作れます。

Pythonで小数点の四捨五入/切り捨て/切り上げを行う

Pythonのdecimalモジュールを使って、小数点の丸めを行う方法です。

pipコマンドまとめ! 忘れても思い出せばいい! 【Python TIPS】

よく使うpipコマンドをまとめました。

Pythonで正規表現を使って数値/英字チェックを実装する (コピペ用)

数値/半角英字などのチェック処理を、Pythonの正規表現を使って実装します。
コピペで簡単に使えるようになっています。

[SQLAlchemy] one() / first()の違いと使い分け

PythonのSQLAlchemyで、1件のレコードを取得する関数に、one()とfirst()関数の2つがある。
この2つの関数の違いが気になったので、まとめます。
関数の説明と、その使い分け方についても、解説したいと思います。

スポンサーリンク

QooQ