【Webスクレイピング応用・完結編】複数ページ巡回(クローリング)とPandas/Matplotlibでの分析・可視化 🤖
「1ページ分のデータは取れたけど、サイトにある何十ページもの情報を全部集めるにはどうすればいいの?」
「スクレイピングで集めたデータを、ただ眺めるだけじゃなくて、何か意味のある分析をしてみたい!」
「データ収集から分析、グラフ化まで、一連の流れを全部Pythonで完結させたい!」
こんにちは! Webスクレイピング探検隊、隊長のPythonistaです! 前回の第2回では、ブラウザの開発者ツールを駆使して現実的なニュースサイトのHTMLを分析し、記事の見出しとリンクを抽出してCSVファイルに保存する、という実践的なスキルをマスターしましたね。
いよいよシリーズ最終回となる今回は、これまでの知識を総動員し、Webスクレイピングの冒険を完結させます! 今回のテーマは、
- 単一ページから、複数ページを自動で巡回する「クローリング」へのステップアップ
- クローリングで収集した大量のデータを、Pandasで読み込み、簡単なテキスト分析を行う
- 分析結果をMatplotlibでグラフ化し、データから洞察を得る
という、データ収集から分析・可視化までの一連のデータ分析プロジェクトです。この記事を終える頃には、あなたはWebから自力で情報を集め、それを意味のある形に変えるという、データサイエンティストのような体験をすることができるでしょう。さあ、冒険のクライマックスです!
1. 準備:これまでの知識と新しいHTMLサンプル
今回は、これまでに学んだ多くのライブラリを組み合わせます。インポート文も賑やかになりますね!
import requests
from bs4 import BeautifulSoup
import csv
import time # クローリングのマナーとして必須!
import pandas as pd
import matplotlib.pyplot as plt
from collections import Counter
import re
今回のターゲット:複数ページのニュースサイト
複数ページを巡回するために、前回作成したmock_news.html
を少し改造し、ページネーション(ページ送り)のリンクを追加したサンプルを用意します。以下の2つのHTMLファイルを作成し、スクリプトと同じディレクトリに保存してください。
mock_news_page1.html
:
<!DOCTYPE html>
<html lang="ja">
<!-- (head部分は省略) -->
<body>
<h1>TechTrend Today - 1ページ目</h1>
<div class="article-list">
<div class="article-entry"><h2 class="article-title"><a href="/news/001">Python、次期バージョンで画期的な新機能を追加か</a></h2></div>
<div class="article-entry"><h2 class="article-title"><a href="/news/002">AIが描く未来の都市デザインとは</a></h2></div>
<div class="article-entry"><h2 class="article-title"><a href="/news/003">量子コンピュータ、実用化への大きな一歩</a></h2></div>
</div>
<div class="pagination">
<a href="mock_news_page2.html">次のページへ >></a>
</div>
</body>
</html>
mock_news_page2.html
:
<!DOCTYPE html>
<html lang="ja">
<!-- (head部分は省略) -->
<body>
<h1>TechTrend Today - 2ページ目</h1>
<div class="article-list">
<div class="article-entry"><h2 class="article-title"><a href="/news/004">データサイエンスで変わる、新しい農業の形</a></h2></div>
<div class="article-entry"><h2 class="article-title"><a href="/news/005">PythonとRust、注目の連携フレームワークが登場</a></h2></div>
</div>
<div class="pagination">
<span>これ以上ページはありません</span>
</div>
</body>
</html>
2. ステップ1:複数ページを巡回する「クローラー」の実装
単一ページの情報を取得する「スクレイパー」から、複数のページをたどる「クローラー」へと進化させましょう。
2.1. クローリングのロジック
基本的な考え方はシンプルです。
- 最初のページにアクセスしてデータを抽出する。
- そのページに「次のページへ」のリンクがあるか探す。
- リンクがあれば、そのリンク先のURLにアクセスしてデータを抽出する。
- 「次のページへ」のリンクがなくなるまで、2と3を繰り返す。
このロジックを、for
ループやwhile
ループを使って実装します。今回は、取得するページ数をあらかじめ決めておく簡単なfor
ループで実装してみましょう。
2.2. スクリプトの統合とクローリング機能の追加
前回のスクリプトをベースに、複数ページを巡回する機能を追加します。
# 前回のextract_articles_from_html関数とsave_to_csv関数は再利用
# (ここでは省略。完全なコードは最後に掲載します)
def main_crawler():
base_url = "http://example.com/" # 架空のベースURL
# 今回はローカルファイルなので、ファイル名のリストを用意
target_files = ['mock_news_page1.html', 'mock_news_page2.html']
all_articles = [] # 全てのページから集めた記事を格納するリスト
for page_file in target_files:
print(f"\n'{page_file}' をスクレイピング中...")
try:
# ローカルファイルを開く (実際のWebサイトなら requests.get() を使う)
with open(page_file, 'r', encoding='utf-8') as f:
content = f.read()
# 1ページ分の記事を抽出
articles_on_page = extract_articles_from_html(content, base_url) # (後で関数を少し改造)
if articles_on_page:
all_articles.extend(articles_on_page) # 結果を総合リストに追加
print(f" {len(articles_on_page)}件の記事を抽出しました。")
# 【重要】相手サーバーに負荷をかけないためのマナー
print(" 1秒待機します...")
time.sleep(1)
except FileNotFoundError:
print(f" エラー: ファイル '{page_file}' が見つかりません。")
except Exception as e:
print(f" 予期せぬエラー: {e}")
print(f"\nクローリング完了。合計 {len(all_articles)}件の記事を収集しました。")
# 全ての記事データをCSVに保存
save_to_csv(all_articles, 'all_news_headlines.csv')
# (extract_articles_from_html関数は、相対URLを絶対URLに変換するよう少し改造が必要)
# from urllib.parse import urljoin # URLを結合するために使う
# url = urljoin(base_url, link.get('href')) のようにする
このロジックで、複数のページからデータを集めて、一つのリストall_articles
に格納することができました。time.sleep(1)
が、実際のWebサイトをクローリングする際の重要なマナーです。
3. ステップ2:Pandasによるデータ分析
収集したデータをCSVファイルに保存したら、次はそのデータを分析します。ここからがPandasの出番です!
3.1. CSVファイルをDataFrameに読み込む
import pandas as pd
csv_file_path = 'all_news_headlines.csv'
try:
df = pd.read_csv(csv_file_path)
print("\n--- CSVから読み込んだDataFrame ---")
print(df)
except FileNotFoundError:
print(f"ファイル '{csv_file_path}' が見つかりません。先にクローラーを実行してください。")
df = pd.DataFrame() # 空のDataFrameを作成
3.2. 簡単なテキスト分析:単語の頻度をカウント
収集した記事のタイトルに、どのような単語がよく使われているかを調べてみましょう。collections.Counter
が役立ちます。
from collections import Counter
import re
# dfが読み込まれている前提
if not df.empty:
# 全てのタイトルを一つの大きな文字列に結合
all_titles = ' '.join(df['title'])
# 正規表現で単語(アルファベットのみ)を抽出
words = re.findall(r'[a-zA-Z]+', all_titles.lower())
# Counterで単語の出現頻度をカウント
word_counts = Counter(words)
print("\n--- タイトル内の単語頻度 Top 5 ---")
# most_common(N)で上位N件を取得
for word, count in word_counts.most_common(5):
print(f"{word}: {count}回")
(注:日本語の単語頻度を正確に行うには、MeCabやJanomeといった形態素解析ライブラリが必要になります。今回は簡単にするため、アルファベットの単語のみを対象としています。)
4. ステップ3:Matplotlibによる可視化
最後に、分析結果を棒グラフにして視覚的に分かりやすく表現しましょう。
# word_counts が計算済みとする
if 'word_counts' in locals() and word_counts:
# 上位10件のデータを準備
top_10_words = word_counts.most_common(10)
labels, values = zip(*top_10_words) # ラベルと値のリストに分割
plt.style.use('ggplot')
plt.figure(figsize=(10, 6))
# 水平棒グラフを作成
plt.barh(labels, values, color='#3498db')
# 上位が上に来るようにY軸を反転
plt.gca().invert_yaxis()
plt.title('ニュースタイトル頻出単語 Top 10')
plt.xlabel('出現回数')
plt.tight_layout()
plt.show()
これで、Webからデータを自動で収集し、分析し、その結果をグラフで表現するという、データ分析の基本的なパイプラインを全てPythonで完遂することができました!
まとめ:Webスクレイピング入門シリーズ完結!
3回にわたるWebスクレイピング入門シリーズ、お疲れ様でした!このシリーズを通して、私たちは以下の壮大な旅をしました。
- 第1回: `requests`と`BeautifulSoup4`を使い、単一のWebページから情報を抽出する基本をマスターした。
- 第2回: ブラウザの開発者ツールでHTMLを分析し、抽出したデータをCSVファイルに保存する実践的なスキルを身につけた。
- そして今回: 複数ページを自動巡回する「クローリング」にステップアップし、収集したデータを`Pandas`と`Matplotlib`で分析・可視化する、一連のプロジェクトを完成させた。
Webスクレイピングは、インターネットという無限の情報源からデータを取得するための強力な技術です。そして、そのデータを分析・可視化することで、これまで見えなかった新しい発見や洞察を得ることができます。今回学んだワークフローは、そのための非常に重要な第一歩です。
ぜひ、今回作成したクローラーをベースに、あなたの興味のあるサイト(ルールとマナーは必ず守ってくださいね!)からデータを集め、独自の分析に挑戦してみてください。あなたのプログラミングの世界は、ここからさらに大きく広がっていきます!
これまでの探検、ありがとうございました! Happy Scraping & Analyzing! 🤖
コメント
コメントを投稿