【Python】正規表現を使ったWebスクレイピング

スクレイピングはWebサイトから情報を収集する方法の一つです。これを効率的に行うために、世の中には便利なライブラリやフレームワークがたくさんリリースされています。
しかし、今回は敢えてこの流れに反して、正規表現を使ってスクレイピングをしてみようと思います。これによってスクレイピングの基本を理解できると思います。
# 2020/3/20 記事更新

確認した環境

  • OS: Ubuntsu16.04LTS
  • Python3.7.4

Webスクレイピングって何?

スクレイピングとは、WebサイトのHTML構造を解析して目的とする情報を取得することです。
以下のサイト様が参考になると思います。

スクレイピングはサーバサイドのプログラミング言語を使って外部サーバへアクセスし、そのコンテンツから自分たちの欲しい情報を引き出す手法です。多くはHTMLを返す場合に使われ、DOMを解析したり正規表現を使ってデータを抜き出します。
引用元サイト:スクレイピングとAPIの違い

正規表現を使ったスクレイピング

スクレイピングは基本的に下記の手順で行います。

  1. WebサイトのHTMLデータを取得
  2. 得られたHTMLデータを解析し、目的のデータを抽出

例として日本経済新聞のWebサイト(nikkei.com)のトップページの記事タイトルを抽出してみます。

WebサイトのHTMLデータを取得する

requestsモジュール を使って目的のWebサイトのHTMLデータを取得します。

>>> import requests

# 日本経済新聞のWebサイトのURL
>>> url = 'https://www.nikkei.com'

# get()メソッドでHTMLデータを取得
>>> res = requests.get(url)

# 正常に抜き出せたかステータス確認
>>> res.status_code == requests.codes.ok
True

text属性を使って取得データを確認しました。正常に取得できているようです。

>>> res.text[:250]
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r\n\r\n<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja" dir="ltr" id="R1">\r\n<head>\r\n<meta http-equiv="Content-Lang'

(参考記事)【Python】 GET・POSTリクエストによるWebデータの取得(Requestsモジュール)

HTMLデータを解析して目的の情報を取得

冒頭にも述べたように、今回は正規表現を使って記事タイトルを抽出します。

(1)取得したい箇所のHTMLスクリプトのパターンを調べる

まず、該当する箇所のHTMLスクリプトを確認します。
Chromeの場合は、ディベロッパーツールを使って簡単に調べることができます。

<ディベロッパーツールでの調べ方>

  • ディベロッパーツールを起動する
  • 「Chromeの設定」−「その他のツール(L)」-「デベロッパーツール(D)」を選択(下図の赤枠部)

  • 該当部分のHTMLスクリプトを見つける
  • 下図の赤枠部のアイコンをクリック後、サイト上の任意箇所をクリックすると、Elementsウインドウに表示されているHTMLスクリプトの該当箇所がハイライトされます。

今回は下記のように記述されていました。他の箇所もこれと同じパターンで記述されているようです。

<a class="k-card__block-link" href="/article/DGXMZO57053850Q0A320C2MM8000" tabindex="-1">
  <span class="k-v">一斉休校を延長せず 首相、イベント開催「慎重に」</span>
</a>

(2)正規表現を使って記事タイトルを抜き出す

HTMLスクリプトのパターンが分かったら、次は正規表現を使って正規表現オブジェクトを生成します。例えば、

# reモジュールをインポート
>>> import re

# 正規表現オブジェクトの生成
>>> regex = re.compile(r'<a class="k-card__block-link".*?><span class="k-v">.+?</span></a>')

reモジュールのre.findall() を使って、この正規表現パターンにマッチした箇所(=この場合は記事タイトル)を全て抽出します。

# findall()を使って正規表現にマッチした箇所を全部抽出しリストに格納
>>> subtitles = regex.findall(res.text)

# 更に正規表現を使って、要素のみを抽出
>>> for l in subtitles:
...     t = re.search(r'<span.+>(.+)</span>', l).group(1)
...     print(t)

# 出力結果
一斉休校を延長せず 首相、イベント開催「慎重に」
ドル、34年ぶり高値に 資金確保に世界が殺到
  :
 (省略)
  :
佐賀銀、人事異動を2週間凍結 継続的な顧客対応優先
北九州のぬか炊き 地味でも滋味、魚や肉を煮付け

うまく抽出できたようです。

尚、上記をまとめたコード例をこちらに挙げておりますので、興味があればご参照ください。
Webサイトへのアクセス時の応答エラー対応なども追記しています。

(参考記事)
【Python】正規表現 reモジュールの使いかたの基本
【Python】文字列を検索する(in演算子、find、正規表現)

まとめ

正規表現を使ったスクレイピングのやり方についてまとめました。
今回は、目的の要素を的確に抽出するための「正規表現パターン」を作るにあたってかなり試行錯誤しました。余計な要素まで抽出されてしまったり、逆に必要な要素が抽出できていなかったり・・・

こういった苦労を解決してくれるのが、BeautifulSoupのような便利なライブラリです。
使い方についてはこちらの記事(【Python】BeautifulSoupを使ったWebスクレイピング )で解説していますので、併せてご参照ください!

Learn more...

書籍でもう少し詳しく学びたい場合はこちらもどうぞ。筆者もかなり参考にさせてもらっています!