AIが生成しがちな「いかにもAIっぽい」日本語の定型表現・水増し・空疎な形容を取り除き、読者の信頼を損なわない自然な文章に直す。記事・原稿・プレスリリース・告知・SNS投稿など、AIの支援を受けて書いた文章を公開前に点検するときに使う。「AI臭を消したい」「文章が機械っぽい」「人が書いたように直したい」などの依頼で使う。
page-kanshi
ウェブページの変化検知・更新監視・到達性(ダウン)監視の手法。行政サイトや企業サイトの「こっそり修正」を捉える、削除前にページを保全する、RSSのないページから簡易フィードを生成する、変更時にWebhookで通知する、変更検知時に自動でアーカイブする、といった調査報道の場面で使う。
Visualping・Distill.io・UptimeRobot・changedetection.io・urlwatch などの監視手段を扱う。
実行スコア 未検証
インストール方法を見る含まれるファイル(1)
- SKILL.md30.7 KB
SKILL.md(原文)
インストールする前に、エージェントに与えられる指示の中身を確認できます。
ウェブページ監視(変化検知・更新監視)
ウェブページの変化を追い、コンテンツの削除や差し替えを検知し、重要なページが消える前に保全するための手法集。 行政・企業の公式ページが告知なく書き換えられる「こっそり修正(サイレント修正)」を捉えることは、調査報道の基礎的な技術になる。
注意:監視は対象サイトに負荷をかける行為でもある。
robots.txtと各サイトの利用規約を確認し、頻度を抑え、公開ページのみを対象にする。アクセス制御(ログイン・有料壁)を回避しないこと。本スキルは一般的な手引きであり、法的助言ではない。具体の可否は提出・実施前に各サイトの規約と最新の法令で確認する。
監視サービスの比較
無料枠の上限や履歴の保存期間は毎年のように変わる。特定の数値に依存する前に、各サービスの料金ページで最新を確認すること。下表は2026年時点のスナップショット。
| サービス | 無料枠 | 向いている用途 | 履歴 | 通知の速さ |
|---|---|---|---|---|
| Visualping | 1日あたり数回のチェック(近年は無料枠が縮小) | 見た目の変化 | 標準 | 数分 |
| ChangeTower | あり(現行の上限は要確認) | コンプライアンス・アーカイブ | 有料プランで複数年 | 数分 |
| Distill.io | 監視5件程度・履歴7日 | 要素単位の追跡 | 無料枠では限定的 | 数秒 |
| Wachete | 限定的 | ログイン保護ページ | 12か月 | 数分 |
| UptimeRobot | 50件を5分間隔(無料SMSは廃止) | 死活監視のみ | 60日 | 5分間隔 |
| changedetection.io | セルフホスト(無料) | プライバシー重視・自前運用 | ディスク容量次第 | 設定可能 |
| urlwatch | セルフホスト(無料) | cron駆動のCLI | 設定可能 | 設定可能 |
いずれも海外の汎用サービス(日本語UIの有無は各サービスで異なる)。料金・無料枠は変動が大きいため契約前に確認する。秘匿性の高い取材では、外部サービスに監視対象URLを預けないセルフホスト型(changedetection.io / urlwatch)や、後述の自前スクリプトが安全。
クイックスタート:ページを監視する
Distill.io の要素監視
// Distill.io は CSS/XPath セレクタで監視範囲を精密に指定できる
// よくある用途のセレクタ例:
// ニュース記事の見出しを監視
const newsSelector = '.article-headline, h1.title, .story-title';
// 価格の変化を監視
const priceSelector = '.price, .product-price, [data-price]';
// 在庫・提供状況を監視
const availabilitySelector = '.in-stock, .availability, .stock-status';
// 特定の段落・セクションを監視
const sectionSelector = '#main-content p:first-child';
// 表データを監視
const tableSelector = 'table.data-table tbody tr';
行政の告示・お知らせ欄、入札・調達情報、審議会の開催案内、企業のIR・プレスリリース一覧などは、見出しリストや更新日のセレクタを狙うと差分が取りやすい。
Python による監視スクリプト
import requests
import hashlib
import json
import smtplib
from email.mime.text import MIMEText
from datetime import datetime
from pathlib import Path
from typing import Optional
from bs4 import BeautifulSoup
class PageMonitor:
"""ローカル保存型のシンプルなページ変化監視。"""
def __init__(self, storage_dir: Path):
self.storage_dir = storage_dir
self.storage_dir.mkdir(parents=True, exist_ok=True)
self.state_file = storage_dir / 'monitor_state.json'
self.state = self._load_state()
def _load_state(self) -> dict:
if self.state_file.exists():
return json.loads(self.state_file.read_text())
return {'pages': {}}
def _save_state(self):
self.state_file.write_text(json.dumps(self.state, indent=2))
def _get_page_hash(self, url: str, selector: Optional[str] = None) -> tuple[str, str]:
"""ページ全体、または特定要素のハッシュと本文を取得する。"""
response = requests.get(url, timeout=30, headers={
'User-Agent': 'Mozilla/5.0 (PageMonitor/1.0)'
})
response.raise_for_status()
if selector:
soup = BeautifulSoup(response.text, 'html.parser')
element = soup.select_one(selector)
content = element.get_text(strip=True) if element else ''
else:
content = response.text
content_hash = hashlib.sha256(content.encode()).hexdigest()
return content_hash, content
def add_page(self, url: str, name: str, selector: Optional[str] = None):
"""監視対象ページを追加する。"""
content_hash, content = self._get_page_hash(url, selector)
self.state['pages'][url] = {
'name': name,
'selector': selector,
'last_hash': content_hash,
'last_check': datetime.now().isoformat(),
'last_content': content[:1000], # プレビューを保存
'change_count': 0
}
self._save_state()
print(f"追加: {name} ({url})")
def check_page(self, url: str) -> Optional[dict]:
"""1ページの変化を確認する。"""
if url not in self.state['pages']:
return None
page = self.state['pages'][url]
selector = page.get('selector')
try:
new_hash, new_content = self._get_page_hash(url, selector)
except Exception as e:
return {
'url': url,
'name': page['name'],
'status': 'error',
'error': str(e)
}
changed = new_hash != page['last_hash']
result = {
'url': url,
'name': page['name'],
'status': 'changed' if changed else 'unchanged',
'previous_content': page['last_content'],
'new_content': new_content[:1000] if changed else None
}
if changed:
page['last_hash'] = new_hash
page['last_content'] = new_content[:1000]
page['change_count'] += 1
# 変更内容をアーカイブ(ローカル保存)
archive_file = self.storage_dir / f"{hashlib.md5(url.encode()).hexdigest()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
archive_file.write_text(new_content)
page['last_check'] = datetime.now().isoformat()
self._save_state()
return result
def check_all(self) -> list[dict]:
"""監視中の全ページを確認する。"""
results = []
for url in self.state['pages']:
result = self.check_page(url)
if result:
results.append(result)
return results
# 使い方
monitor = PageMonitor(Path('./page_monitor_data'))
# 監視対象を追加
monitor.add_page(
'https://example.com/important-page',
'重要ページ',
selector='.main-content' # 任意:特定要素だけを監視
)
# 変化を確認
results = monitor.check_all()
for result in results:
if result['status'] == 'changed':
print(f"変更あり: {result['name']}")
print(f" 変更前: {result['previous_content'][:100]}...")
print(f" 変更後: {result['new_content'][:100]}...")
このスクリプトはハッシュ比較で「変わったかどうか」を検知する。実際に何が変わったかは、保存した本文どうしを
difflib(Python標準)などで差分表示すると、削除・追記・差し替えを具体的に追える。
死活監視(ページのダウン検知)
UptimeRobot API 連携
import requests
from typing import List, Optional
class UptimeRobotClient:
"""ページの到達性を監視する UptimeRobot API クライアント。"""
def __init__(self, api_key: str):
self.api_key = api_key
# v2 は 2026 時点でも動作するが保守モード。現行の REST API は
# https://api.uptimerobot.com/v3 で、リクエスト形式が異なる
#(Bearer 認証・JSON ボディ)。
self.base_url = "https://api.uptimerobot.com/v2"
def _request(self, endpoint: str, params: dict = None) -> dict:
data = {'api_key': self.api_key}
if params:
data.update(params)
response = requests.post(f"{self.base_url}/{endpoint}", data=data)
return response.json()
def get_monitors(self) -> List[dict]:
"""すべての監視を取得する。"""
result = self._request('getMonitors')
return result.get('monitors', [])
def create_monitor(self, friendly_name: str, url: str,
monitor_type: int = 1) -> dict:
"""新しい監視を作成する。
種別: 1=HTTP(s), 2=キーワード, 3=Ping, 4=ポート
"""
return self._request('newMonitor', {
'friendly_name': friendly_name,
'url': url,
'type': monitor_type
})
def get_monitor_uptime(self, monitor_id: int,
custom_uptime_ratios: str = "7-30-90") -> dict:
"""監視の稼働率統計を取得する。"""
return self._request('getMonitors', {
'monitors': monitor_id,
'custom_uptime_ratios': custom_uptime_ratios
})
def pause_monitor(self, monitor_id: int) -> dict:
"""監視を一時停止する。"""
return self._request('editMonitor', {
'id': monitor_id,
'status': 0
})
def resume_monitor(self, monitor_id: int) -> dict:
"""監視を再開する。"""
return self._request('editMonitor', {
'id': monitor_id,
'status': 1
})
# 使い方
client = UptimeRobotClient('your-api-key')
# 重要ページの監視を作成
client.create_monitor('ニュース トップ', 'https://example-news.com')
client.create_monitor('API ステータス', 'https://api.example.com/health')
# すべての監視状態を確認
for monitor in client.get_monitors():
status = '稼働中' if monitor['status'] == 2 else 'ダウン'
print(f"{monitor['friendly_name']}: {status}")
死活監視は「告知のない公開停止」を捉えるのにも使える。たとえば、問題が報じられた直後に行政・企業の特定ページだけが消える、選挙期間中に候補者の公約ページが落ちる、といった動きをタイムスタンプ付きで記録できる。
RSSフィードの生成
RSSのないページから簡易フィードを作る
import requests
from bs4 import BeautifulSoup
from feedgen.feed import FeedGenerator
from datetime import datetime
import hashlib
class RSSGenerator:
"""ウェブページから RSS フィードを生成する。"""
def __init__(self, feed_id: str, title: str, link: str):
self.fg = FeedGenerator()
self.fg.id(feed_id)
self.fg.title(title)
self.fg.link(href=link)
self.fg.description(f'{title} の自動生成フィード')
def add_from_page(self, url: str, item_selector: str,
title_selector: str, link_selector: str,
description_selector: Optional[str] = None):
"""ページを解析し、項目をフィードに追加する。
引数:
url: 解析対象ページのURL
item_selector: 各項目コンテナの CSS セレクタ
title_selector: タイトルの CSS セレクタ(項目に対する相対)
link_selector: リンクの CSS セレクタ(項目に対する相対)
description_selector: 概要の CSS セレクタ(任意)
"""
response = requests.get(url, timeout=30)
soup = BeautifulSoup(response.text, 'html.parser')
items = soup.select(item_selector)
for item in items[:20]: # 最大20件に制限
title_elem = item.select_one(title_selector)
link_elem = item.select_one(link_selector)
if not title_elem or not link_elem:
continue
title = title_elem.get_text(strip=True)
link = link_elem.get('href', '')
# 相対URLなら絶対URLに変換
if link.startswith('/'):
from urllib.parse import urljoin
link = urljoin(url, link)
fe = self.fg.add_entry()
fe.id(hashlib.md5(link.encode()).hexdigest())
fe.title(title)
fe.link(href=link)
if description_selector:
desc_elem = item.select_one(description_selector)
if desc_elem:
fe.description(desc_elem.get_text(strip=True))
fe.published(datetime.now())
def generate_rss(self) -> str:
"""RSS の XML 文字列を生成する。"""
return self.fg.rss_str(pretty=True).decode()
def save_rss(self, filepath: str):
"""RSS フィードをファイルに保存する。"""
self.fg.rss_file(filepath)
# 例:RSSのないニュースサイトのフィードを生成
rss = RSSGenerator(
'https://example.com/news',
'Example ニュース フィード',
'https://example.com/news'
)
rss.add_from_page(
'https://example.com/news',
item_selector='.news-item',
title_selector='h2 a',
link_selector='h2 a',
description_selector='.summary'
)
# フィードを保存
rss.save_rss('example_feed.xml')
日本の行政サイトは、お知らせ欄にRSSがないか、あっても更新が滞っていることが少なくない。一覧ページの構造(日付+見出し+リンク)が安定していれば、この方式で自前フィードを作り、RSSリーダーやチャット通知に流し込める。
RSS-Bridge(セルフホスト)の利用
# RSS-Bridge は、RSS を提供していないサイト向けにフィードを生成する
# X(旧Twitter)、Instagram、YouTube など多くのサイトに対応
# Docker でのインストール
docker pull rssbridge/rss-bridge
docker run -d -p 3000:80 rssbridge/rss-bridge
# http://localhost:3000 にアクセス
# ブリッジを選び、パラメータを入力すると RSS フィードURLが得られる
SNSの監視
SNSの大量取得・保存は各プラットフォームの規約と認証要件に強く依存する。米国発のツールが多いが、利用可否・課金は地域に関わらず各サービスの最新規約で確認すること。
X(旧Twitter)のアーカイブ(Twarc)
# Twarc は X(Twitter) API の認証情報を必要とする。
#
# 重要(2023年以降): X は無料の Twitter API 枠と、学術研究向けの
# 無料アクセスを廃止した。X API の料金はその後も複数回改定されており、
# Basic / Pro / Enterprise の階層名や従量課金モデルは変わっている。
# 費用見積もりの前に、必ず現行の料金ページ
# https://developer.x.com/en/products/x-api を確認すること。
# 一度きりのアーカイブなら、snscrape / nitter / Web スクレイピング系の
# 経路の方が安上がりな場合がある(web スクレイピングのスキルを参照)。
# インストール
# pip install twarc
# 設定(対話式 — API キーとベアラートークンを登録)
# twarc2 configure
import subprocess
import json
from pathlib import Path
class TwitterArchiver:
"""X(Twitter) の検索結果・タイムラインをアーカイブする。"""
def __init__(self, output_dir: Path):
self.output_dir = output_dir
self.output_dir.mkdir(parents=True, exist_ok=True)
def search(self, query: str, max_results: int = 100) -> Path:
"""ツイートを検索してファイルに保存する。"""
output_file = self.output_dir / f"search_{query.replace(' ', '_')}.jsonl"
subprocess.run([
'twarc2', 'search',
'--max-results', str(max_results),
query,
str(output_file)
], check=True)
return output_file
def get_timeline(self, username: str, max_results: int = 100) -> Path:
"""ユーザーのタイムラインを取得する。"""
output_file = self.output_dir / f"timeline_{username}.jsonl"
subprocess.run([
'twarc2', 'timeline',
'--max-results', str(max_results),
username,
str(output_file)
], check=True)
return output_file
def parse_archive(self, filepath: Path) -> list[dict]:
"""アーカイブしたツイートを読み込む。"""
tweets = []
with open(filepath) as f:
for line in f:
data = json.loads(line)
if 'data' in data:
tweets.extend(data['data'])
return tweets
公人・公的アカウントの投稿が削除・修正される動きを捉えるなら、削除前に保存しておく発想が要る。スクリーンショットだけでなく、本文・投稿日時・URLを機械可読な形(JSONなど)で残すと、後の検証・記事化に使いやすい。
Webhook 通知
変更時にアラートを送る
import requests
from datetime import datetime
from typing import Optional
class AlertManager:
"""監視ページが変化したらアラートを送る。"""
def __init__(self, slack_webhook: str = None,
discord_webhook: str = None,
email_config: dict = None):
self.slack_webhook = slack_webhook
self.discord_webhook = discord_webhook
self.email_config = email_config
def send_slack(self, message: str, channel: str = None):
"""Slack に通知を送る。"""
if not self.slack_webhook:
return
payload = {'text': message}
if channel:
payload['channel'] = channel
requests.post(self.slack_webhook, json=payload)
def send_discord(self, message: str):
"""Discord に通知を送る。"""
if not self.discord_webhook:
return
requests.post(self.discord_webhook, json={'content': message})
def send_email(self, subject: str, body: str, to: str):
"""メールで通知を送る。"""
if not self.email_config:
return
import smtplib
from email.mime.text import MIMEText
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = self.email_config['from']
msg['To'] = to
with smtplib.SMTP(self.email_config['smtp_host'],
self.email_config['smtp_port']) as server:
server.starttls()
server.login(self.email_config['username'],
self.email_config['password'])
server.send_message(msg)
def alert_change(self, page_name: str, url: str,
old_content: str, new_content: str):
"""設定済みの全チャンネルに変更アラートを送る。"""
message = f"""
ページ変更を検知: {page_name}
URL: {url}
時刻: {datetime.now().isoformat()}
変更前(プレビュー):
{old_content[:200]}...
変更後(プレビュー):
{new_content[:200]}...
"""
if self.slack_webhook:
self.send_slack(message)
if self.discord_webhook:
self.send_discord(message)
Slack / Discord は海外サービスだが日本でも広く使われる。社内チャット(Microsoft Teams、LINE WORKS 等)にも、たいていは「受信Webhook(Incoming Webhook)」の仕組みがあり、上記と同じ要領でJSONをPOSTすれば通知できる。
cron による定期監視
継続監視のための cron 設定
# crontab を編集
crontab -e
# 15分ごとにページをチェック
*/15 * * * * /usr/bin/python3 /path/to/monitor_script.py >> /var/log/monitor.log 2>&1
# 重要ページは5分ごとにチェック
*/5 * * * * /usr/bin/python3 /path/to/critical_monitor.py >> /var/log/critical.log 2>&1
# 毎朝8時に日次サマリーを送信
0 8 * * * /usr/bin/python3 /path/to/daily_report.py
頻度は「変わりうる速さ」と「相手サイトへの負荷」のバランスで決める。多くの行政告知は日次〜時間単位で十分。秒単位の監視は、対象が明確に高頻度更新(速報・在庫・株価等)で、かつ規約・負荷の面で問題ない場合に限る。
監視スクリプトのテンプレート
#!/usr/bin/env python3
"""cron 実行用のページ監視スクリプト。"""
import sys
from pathlib import Path
from datetime import datetime
# プロジェクトをパスに追加
sys.path.insert(0, str(Path(__file__).parent))
from monitor import PageMonitor
from alerts import AlertManager
def main():
# 初期化
monitor = PageMonitor(Path('./data'))
alerts = AlertManager(
slack_webhook='https://hooks.slack.com/services/...',
discord_webhook='https://discord.com/api/webhooks/...'
)
# 全ページをチェック
results = monitor.check_all()
# 結果を仕分け
changes = [r for r in results if r['status'] == 'changed']
errors = [r for r in results if r['status'] == 'error']
# 変更を通知
for change in changes:
alerts.alert_change(
change['name'],
change['url'],
change['previous_content'],
change['new_content']
)
print(f"[{datetime.now()}] 変更: {change['name']}")
# エラーを通知
for error in errors:
alerts.send_slack(f"監視エラー {error['name']}: {error['error']}")
print(f"[{datetime.now()}] エラー: {error['name']} - {error['error']}")
# サマリー
print(f"[{datetime.now()}] {len(results)}ページを確認、"
f"変更{len(changes)}件、エラー{len(errors)}件")
if __name__ == '__main__':
main()
変更検知時の自動アーカイブ
変化を検知したら自動で保全する
# `MultiArchiver` は姉妹スキル「web-archive(ウェブアーカイブ)」の
# 多重アーカイブ用ヘルパー。自前の多重アーカイバに置き換えるか、
# 当該スキルの MultiArchiver クラスを移植して使う。
from multiarchiver import MultiArchiver
class ArchivingMonitor(PageMonitor):
"""変化を検知したらコンテンツをアーカイブする監視。"""
def __init__(self, storage_dir: Path):
super().__init__(storage_dir)
self.archiver = MultiArchiver()
def check_page(self, url: str) -> dict:
"""ページを確認し、変化していればアーカイブする。"""
result = super().check_page(url)
if result and result['status'] == 'changed':
# 複数サービスへアーカイブ
archive_results = self.archiver.archive_url(url)
successful_archives = [
r.archived_url for r in archive_results
if r.success
]
result['archives'] = successful_archives
# アーカイブURLを記録
print(f"{url} をアーカイブ:")
for archive_url in successful_archives:
print(f" - {archive_url}")
return result
「こっそり修正」の立証では、変更前後の両方が証拠になる。変更検知の瞬間に、Wayback Machine(archive.org)や archive.today などの外部アーカイブへ保存しておくと、第三者が確認できる客観的な記録が残る。あわせて、取得時刻・取得元URL・ハッシュ値をローカルにも控える。日本のサイトを長期保全する観点では、国立国会図書館WARP(インターネット資料収集保存事業)に既に収集された版がないかも確認に値する。
用途別の監視戦略
ニュース・行政情報の監視
## ニュース/時事の監視
### 監視するページ:
- 速報・新着のセクション
- 報道発表(プレスリリース)ページ
- 行政の告示・お知らせ・審議会案内
- 企業のニュースルーム・IR
### 監視頻度:
- 速報: 5分ごと
- 報道発表: 15〜30分ごと
- 一般ニュース: 1時間ごと
### アーカイブ方針:
- 検知時に即アーカイブ
- Wayback Machine と archive.today を併用
- タイムスタンプ付きでローカルにも保存
「こっそり修正」を捉える監視
## サイレント修正(無告知の書き換え)の監視
### 監視するページ:
- 行政の発表文・統計ページ・Q&A・要綱
- 規約・約款・プライバシーポリシー
- 企業の謝罪文・製品仕様・採用情報
- 公人・公的アカウントのプロフィール/公約ページ
### 着目する変化:
- 数値・日付・固有名詞の差し替え
- 一文・段落の削除(不都合な記述の消去)
- 「更新日」を変えずに本文だけ変える操作
- ページごと削除して別URLに移す操作
### 記録すべきこと:
- 変更前後の全文(差分つき)
- それぞれの取得時刻・URL・ハッシュ
- 外部アーカイブのURL(第三者検証用)
調査・研究の監視
## 学術・研究の監視
### 監視するページ:
- プレプリントサーバ(arXiv、SSRN、J-STAGE のオンライン先行公開 等)
- 学術誌の目次(TOC)
- 学会・会議のプログラム
- 研究者のプロフィール
### 監視頻度:
- 注力テーマは日次
- 一般的な監視は週次
### 推奨ツール:
- Google Scholar アラート(無料・標準機能)
- CiNii / J-STAGE の新着・RSS(提供がある場合)
- RSS が提供されていればそれを利用
- 特定ページには自前監視
競合・対象組織の動向監視
## 対象組織の監視
### 監視するページ:
- 料金・価格ページ
- 製品・サービスページ
- 採用情報(人員動向の手がかり)
- プレスリリース
- 役員・幹部の紹介ページ
### 監視頻度:
- 価格: 日次
- 製品: 日次
- 採用: 週次
- プレス: 日次
### 法的・倫理的な注意:
- 利用規約に違反しない
- アクセス制御を回避しない
- 公開ページのみを対象にする
- 高頻度のスクレイピングをしない
ベストプラクティス
監視前チェックリスト
## ページを監視する前に:
- [ ] そのページは公開されているか(ログイン・有料壁の内側でないか)
- [ ] robots.txt を尊重しているか
- [ ] 監視頻度は妥当か(相手サイトに過度な負荷をかけないか)
- [ ] 取材・報道上の正当な目的があるか
- [ ] 取得データを安全に保管しているか
- [ ] 通知(アラート)を設定したか
- [ ] 重要ページのアーカイブを設定したか
## 保守:
- [ ] 監視を毎月見直す
- [ ] 不要になった監視を削除する
- [ ] ページ構造が変わったらセレクタを更新する
- [ ] 通知が届いているか確認する
- [ ] アーカイブが機能しているか確認する
レート制限(負荷をかけない実装)
import time
from functools import wraps
def rate_limit(min_interval: float = 1.0):
"""関数呼び出しのレートを制限するデコレータ。"""
last_call = [0.0]
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
elapsed = time.time() - last_call[0]
if elapsed < min_interval:
time.sleep(min_interval - elapsed)
last_call[0] = time.time()
return func(*args, **kwargs)
return wrapper
return decorator
# 使い方
@rate_limit(min_interval=2.0) # 最大でも2秒に1回
def check_page(url: str):
return requests.get(url)
監視は相手のサーバ資源を使う。リクエスト間隔を空け(最低1〜3秒)、同一ページを短時間に何度も叩かない。
If-Modified-Since/ETagなどの条件付きリクエストに対応していれば、変更がないときの転送量を減らせる。robots.txt と利用規約を守り、公開ページのみを対象とすることが、継続的に取材を続けるうえでの前提になる。
取材実務上の注意
- 監視で得たのは「変わった」という事実まで。何が・なぜ変わったかは、当事者への取材で確認する。サイレント修正は、システム更新や誤記訂正という正当な理由のこともある。
- 変更検知だけを根拠に書かず、変更前後の保存版・外部アーカイブ・取得時刻を証跡として残す。
- 監視対象URL・取得データの保管は、個人情報保護法および自社の取材倫理規程に従う。秘匿性の高い対象では、外部サービスに監視リストを預けない構成を選ぶ。
- 締切から逆算し、重要ページは早めに監視・保全を始める。消えてからでは取り返せない。
出典・ライセンス(帰属表示)
本スキルは research-toolkit(by Joe Amditis, MIT License, © Joe Amditis,
https://github.com/jamditis/research-toolkit )の skills/page-monitoring を
原典の構成(監視サービス比較・変化検知スクリプト・死活監視・RSS生成・SNS監視・Webhook通知・cron定期実行・変更時の自動アーカイブ・用途別戦略・ベストプラクティス)に沿って日本語化したものです。
米国固有のサービス・文脈は日本/汎用に再構成し、行政・企業サイトの「こっそり修正」を捉える調査報道の文脈、robots.txt・利用規約・負荷への配慮、国立国会図書館WARP や J-STAGE・CiNii など日本の実務を補っています。
コード・スクリプトは機能を保持し、コメントのみ日本語化しています。原典の著作物本文は転載していません。原作者の公認・推奨を受けたものではありません。
MIT ライセンス全文は同梱の LICENSE-MIT.txt を参照。
レビュー
まだレビューはありません。使ってみた感想をお寄せください。
コメント
ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。
まだコメントはありません。最初のコメントを書いてみませんか。
同じリポジトリのスキル
取材・調査・データ報道で使える無料データ源(API)のカタログ。政府統計(e-Stat)、地域経済(RESAS)、気象(気象庁)、法令(e-Gov)、企業開示(EDINET)、書誌・国会会議録(国立国会図書館)、地理空間(国土地理院)、汎用の国際API(GDELT・Open-Meteo・Wayback等)を用途別に整理し、登録要否・利用条件・選び方を示す。「無料のデータ源が欲しい」「このテーマのAPIは?」「公的データをプログラムで取りたい」といった依頼で使う。
データ報道(データジャーナリズム)の手順を支援する。データセットの分析、グラフや地図の作成、雑然としたデータのクリーニング、統計の算出、データに基づく記事の構築に使う。「e-Statのデータを分析したい」「人口あたりで比較したい」「グラフが誤解を招かないか確認したい」「統計から記事を組み立てたい」などの依頼で使う。記者・編集者・調査担当向け。
取材で集めた資料(開示文書・記事・SNS・反訳など)をデジタルアーカイブ化し、AIで要約・分類・エンティティ抽出・関係づけ(知識グラフ化)して横断検索できる調査基盤を作るための手引き。「取材資料を整理したい」「大量の開示文書をデータベース化したい」「人物・組織・出来事の関係を可視化したい」「調査報道のアーカイブを作りたい」などの依頼で使う。
発言・記事・SNS投稿などの主張を体系的にファクトチェックする。主張の抽出、検証可能な命題への分解、根拠の収集、当事者への確認、判定(レーティング)、記録、訂正対応までを支援する。掲載前の裏取り、ファクトチェック記事の作成、編集部の検証手順づくりに使う。「ファクトチェックして」「この発言は本当か」「裏取りの手順を」などの依頼で使う。
テキスト・記事・ウェブページの内容を、厳密な検証方法論にもとづいてファクトチェックする。検証可能な主張を抽出し、信頼できる一次情報・公的データ・検証機関と突き合わせ、各主張の真偽と確からしさ(確信度)、情報源の信頼度スコアを評価し、根拠つきの検証レポートにまとめる。「この主張を検証して」「記事をファクトチェックして」「情報源の信頼性を見て」「真偽を判定して」「誤情報か確かめて」などの依頼で使う。付属の references(信頼できる情報源/検証方法論)を参照する検証重視版。