Live Monitor
STATUS: FETCHING_REALTIME_DATA
技術仕様書:リアルタイム・トレンド解析システム
本ページは、単なるデモではありません。サーバーサイドスクレイピング、DOM解析、そしてAPI設計の完全な実装例を示す技術資料です。 X(旧Twitter)の公式APIに依存せず、公開されているウェブ情報からトレンドを抽出・構造化するエンジンの全貌を公開します。
Target
twittrend.jp (Trend Aggregator)
Method
DOMXPath Parsing / PHP 8.x
コア・アーキテクチャ
このシステムは、サーバーサイド(PHP)で外部サイトのHTMLを取得し、必要な情報だけを抽出してJSON APIとしてフロントエンドに提供する「バックエンド・フォー・フロントエンド(BFF)」パターンを採用しています。
ソースコード完全解説
本番環境で実際に稼働している api/trends.php
の全コードです。エラーハンドリングやUser-Agent偽装など、安定したスクレイピングに必要な要素が網羅されています。
<?php
header('Content-Type: application/json; charset=utf-8');
// 本番環境ではエラー出力を抑制し、APIとしてのJSON整合性を保つ
ini_set('display_errors', 0);
error_reporting(E_ALL);
$response = ['error' => 'An unknown error occurred.'];
try {
// 外部URLアクセスの許可確認
if (!ini_get('allow_url_fopen')) {
throw new Exception('allow_url_fopen is disabled.');
}
$url = 'https://twittrend.jp/';
// User-Agent偽装: 通常のブラウザアクセスに見せかける
$context = stream_context_create([
'http' => [
'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
]
]);
// カスタムエラーハンドラでWarningも例外としてキャッチ
$php_errormsg = '';
set_error_handler(function($errno, $errstr) use (&$php_errormsg) {
$php_errormsg = $errstr;
return true;
});
// ターゲットHTMLの取得
$html = file_get_contents($url, false, $context);
restore_error_handler();
if ($html === false) {
throw new Exception('Fetch failed: ' . $php_errormsg);
}
// DOMParsing: HTMLを構造化データとしてロード
$doc = new DOMDocument();
@$doc->loadHTML('<?xml encoding="UTF-8">' . $html); // @でパースエラー抑制
$xpath = new DOMXPath($doc);
// XPathクエリ: id="now" 内の class="trend" を持つ pタグ直下のリンク
$nodes = $xpath->query('//div[@id="now"]//p[contains(@class, "trend")]/a');
$trends = [];
foreach ($nodes as $i => $node) {
if ($i >= 20) break; // トップ20件に制限
$text = trim($node->textContent);
if (!empty($text)) {
$trends[] = ['rank' => $i + 1, 'text' => $text];
}
}
echo json_encode(['trends' => $trends, 'timestamp' => time()]);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
?>
Key Point: XPath Query
//div[@class="trend"]
のような単純な指定ではなく、親要素のID #now
で範囲を限定しています。これにより、過去のランキングやサイドバーの無関係なリンクの誤検知を防いでいます。
Key Point: Stream Context
多くのWebサイトは、User-Agentが空のアクセスをボットとして遮断します。stream_context_create
で一般的なブラウザの署名をヘッダーに付与することで、これを回避しています。