概要(データ収集BOTは「決まった場所から、決まった情報を黙々と集めてくれるロボット」)
データ収集 BOT は、
「毎日このサイトの価格をチェック」「このAPIから定期的にデータを取得」
といった“繰り返しの情報収集”を、Python に任せる仕組みです。
やっていることはシンプルで、
- どこから(URL / API / ファイル)
- 何を(どの情報・どの項目)
- いつ(毎日 / 毎時 / 定期)
取ってくるかを決めて、それをコードとして固定するだけです。
ここでは、初心者がイメージしやすいように
- 「Webページから情報を取るBOT」
- 「APIから情報を取るBOT」
という2パターンを例に、設計の考え方からコード例、運用で大事なポイントまでかみ砕いて解説します。
基本の考え方(データ収集 BOT を分解すると何をしているのか)
データ収集 BOT の「頭の中」を分解する
どんな BOT も、やっていることはだいたい次の流れに分解できます。
- 行き先を決める
どの URL / API / ファイル / DB から取るかを決める。 - 取り方を決める
HTTP で GET するのか、POST するのか、ヘッダーやパラメータは何か。 - どこを抜くか決める
HTML のどのタグ、JSON のどのキー、レスポンスのどの部分を使うか。 - どう保存するか決める
CSV / Excel / DB / JSON …どの形式で残すか。 - いつ動かすか決める
手動で python を叩くのか、cron/タスクスケジューラで自動実行するのか。
これを「人間の頭の中にあるやり方」から、「Python コード」に翻訳していくのが設計です。
まずは「1回分の収集」をきちんと作る
定期実行や自動化の前に、必ず
「1回分だけ、今からデータを取ってくる」スクリプトを先に作ります。
この 1回分を、
- どこを叩く(URL)
- 何をもらう(HTML / JSON)
- どう取り出す(パース)
- どう保存する(ファイル / DB)
まで含めて“1つの関数”に閉じ込める。
それができてから、cron やバッチに乗せます。
例1:Webページから情報を取るデータ収集 BOT(スクレイピング入門)
ライブラリとプロジェクトの準備
HTML ページからデータを取るときの定番は、
- requests(HTTP通信)
- BeautifulSoup(HTML解析)
の組み合わせです。
あらかじめインストールしておきます。
pip install requests beautifulsoup4
フォルダ構成はシンプルで構いませんが、パス管理のために Path を使う癖をつけておくと後が楽です。
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
DATA_DIR = BASE_DIR / "data"
DATA_DIR.mkdir(exist_ok=True)
Python例:あるニュースサイトの「記事タイトル一覧」を取る
仮に、ニュースサイトのカテゴリページから「記事タイトルだけ」を毎日取得したいとします。
※ 実際にスクレイピングする場合は、対象サイトの利用規約・robots.txt を必ず確認してください。
HTML 構造(開発者ツールで確認)で、記事タイトルがこんな感じだとします。
<h2 class="article-title">
<a href="/news/123">Python 自動化入門</a>
</h2>
HTMLこの場合、クラス article-title の h2 タグを全部拾い、その中の a のテキストを抜けば良いです。
import requests
from bs4 import BeautifulSoup
from datetime import datetime
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
DATA_DIR = BASE_DIR / "data"
DATA_DIR.mkdir(exist_ok=True)
TARGET_URL = "https://example.com/news/python"
def fetch_news_titles():
resp = requests.get(TARGET_URL, timeout=10)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
titles = []
for h2 in soup.select("h2.article-title a"):
title = h2.get_text(strip=True)
link = h2["href"]
titles.append({"title": title, "link": link})
return titles
def save_titles_to_csv(titles):
now = datetime.now().strftime("%Y%m%d_%H%M%S")
out_path = DATA_DIR / f"news_titles_{now}.csv"
import csv
with out_path.open("w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["title", "link"])
writer.writeheader()
writer.writerows(titles)
print(f"保存しました: {out_path}")
def run_bot():
titles = fetch_news_titles()
print(f"取得件数: {len(titles)}")
save_titles_to_csv(titles)
if __name__ == "__main__":
run_bot()
Pythonここで重要なポイントを整理します。
requests.getでページを取得し、raise_for_status()でエラー応答を例外に変えている- BeautifulSoup の
select("h2.article-title a")で、CSS セレクタを使って要素を絞り込んでいる - 必要な情報だけ(タイトルとリンク)を dict にしてリスト化し、それを CSV にしている
この「HTML から必要な部分だけ抜き、構造化されたデータ(リスト・dict)にする」感覚がとても大事です。
例2:API からデータを取る BOT(JSON ベース)
Webスクレイピングと API の違い
スクレイピングは「人間向けの HTML から機械的に情報を引き抜く」方法です。
一方、API は「最初から機械向け(JSONなど)にデータを返す窓口」です。
もし対象サービスに API があるなら、基本的にはスクレイピングより API を使う方が、
- 安定している
- 壊れにくい(HTML レイアウト変更に左右されにくい)
- 利用規約的にも許可されているケースが多い
という点で好ましいです。
例:シンプルな JSON API からデータを取る
仮に、次のような API があるとします。
- エンドポイント:
https://api.example.com/v1/items - パラメータ:
category=python - レスポンス(JSON)は、
itemsの配列を返す
レスポンス例(ざっくり):
{
"items": [
{"id": 1, "name": "Python入門", "price": 1200},
{"id": 2, "name": "自動化レシピ", "price": 1500}
]
}
これを毎日取得して CSV に保存する BOT は、こんな感じになります。
import requests
import csv
from datetime import datetime
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
DATA_DIR = BASE_DIR / "data"
DATA_DIR.mkdir(exist_ok=True)
API_URL = "https://api.example.com/v1/items"
def fetch_items():
params = {"category": "python"}
resp = requests.get(API_URL, params=params, timeout=10)
resp.raise_for_status()
data = resp.json()
return data["items"]
def save_items_csv(items):
now = datetime.now().strftime("%Y%m%d_%H%M%S")
out_path = DATA_DIR / f"items_{now}.csv"
if not items:
print("データがありません")
return
fieldnames = list(items[0].keys())
with out_path.open("w", encoding="utf-8-sig", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(items)
print(f"保存しました: {out_path}")
def run_bot():
items = fetch_items()
print(f"取得件数: {len(items)}")
save_items_csv(items)
if __name__ == "__main__":
run_bot()
Pythonここでのキモは、
resp.json()で JSON を Python の dict / list に変換しているitemsはただの「リスト of dict」なので、そのまま CSV に流せる
という点です。
BOT 設計で本当に大事なところを深掘りする
1. パス設計(BASE_DIR / DATA_DIR をちゃんと決める)
データ収集 BOT は、定期実行(cron / タスクスケジューラ)と組み合わせることが多いです。
このとき「カレントディレクトリがどこか分からない」問題がよく起きます。
そのため、必ず
BASE_DIR = Path(__file__).resolve().parent
DATA_DIR = BASE_DIR / "data"
Pythonのように、「スクリプトが置いてある場所」を基準にフォルダを作っていきます。
こうすると、どこから python bot.py を叩いても、data フォルダの場所がブレません。
2. 例外処理とログ(失敗したことに気づけるようにする)
ネット越しの BOT は、失敗する前提で作ります。
回線落ち、API 側エラー、HTML 構造変更、などなど。
最低限、「失敗時に何が起きたか」をわかるようにしておきます。
簡易的には print でも構いませんが、運用を意識するなら logging がおすすめです。
import logging
LOG_FILE = BASE_DIR / "data_bot.log"
def setup_logging():
logging.basicConfig(
filename=LOG_FILE,
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s"
)
def run_bot():
logging.info("BOT開始")
try:
items = fetch_items()
logging.info(f"取得件数: {len(items)}")
save_items_csv(items)
logging.info("BOT正常終了")
except Exception as e:
logging.exception(f"BOT異常終了: {e}")
raise
Pythonこうしておくと、「昨日の夜の取得が失敗していたのに誰も気づかない」という事故を減らせます。
3. 冪等性(同じ日付のデータをもう一度取り直しても壊れない)
BOT 運用で地味に効いてくるのが“再実行しても壊れないかどうか”です。
例えば、日次データを取る BOT の場合、
YYYYMMDD.csvのように日付別ファイルにする- 同じ日付のファイルが既にある場合の扱いを決める(上書き / スキップ / バックアップ)
などのルールを先に決めておきます。
上書きを許容するなら、こういう感じです。
def get_output_path(prefix: str, date_str: str):
return DATA_DIR / f"{prefix}_{date_str}.csv"
def save_items_csv_for_date(items, date_str):
out_path = get_output_path("items", date_str)
# すでにある場合は上書き(=取り直し)
...
Python逆に「一度取ったら変わらない」系のデータなら、
既にファイルがあればスキップする、という設計もありです。
4. 制約・マナー(アクセス頻度・利用規約)
データ収集 BOT を作ると、つい「たくさん回したくなる」気持ちになりますが、
対象サイトや API にとっては負荷になる場合があります。
意識しておきたいのは、
- robots.txt をチェックして、スクレイピングが許可されているか確認する
- 連続アクセスする場合は
time.sleepで間隔を空ける - API の rate limit(最大リクエスト数/秒や/日)を守る
といった点です。
「人間がブラウザでアクセスする以上の頻度で連打しない」くらいの感覚を持っておくと、
トラブルになりにくくなります。
定期実行と組み合わせて「BOTらしく」していく
1回分ができたら、あとは時間を OS に任せる
ここまでで「run_bot() を呼べば1回分が動く」という状態が作れたら、
いよいよ「BOT化」ができます。
考え方としては、
- Python 側:1回分の処理(今日のデータを取る)
- OS 側:毎日○時に
python bot.pyを実行
と役割を分けます。
Linux / Mac なら cron、Windows ならタスクスケジューラです。
(あなたはすでに cron / タスクスケジューラの話も読んでくれているので、その知識がそのまま活きます。)
実運用イメージ
例えば、「毎日 9:00 にニュースタイトルを収集する BOT」は、
news_bot.pyにrun_bot()を定義crontabに0 9 * * * /usr/bin/python3 /path/to/news_bot.pyを登録
という形になります。
ログを見れば「今日何件取れたか」が分かり、
data フォルダには news_titles_YYYYMMDD_...csv が日々増えていく。
ここまで行くと、もう立派な「データ収集 BOT」です。
まとめ(「1回分の収集を丁寧に作る」がすべての出発点)
データ収集 BOT の核心は、豪華な仕組みではなく、
- どこから何を取ってくるかを明確に決める
- 1回分の収集処理(fetch → parse → save)を関数にまとめる
- パス・ログ・エラー・再実行時の挙動を最初に設計する
- 定期実行は OS(cron / タスクスケジューラ)に任せる
という「地味だけど堅い型」です。
この型を一度自分の手で作ってみると、
- 価格情報の定期取得
- ニュース・ブログ記事タイトルの収集
- 公開APIからの統計データ取り込み
などに、どんどん横展開していけるようになります。
