AI

実験室トップへ / Project: X-Trend-Analyzer

Live Monitor

STATUS: FETCHING_REALTIME_DATA

Source: External Trend Aggregator Update: Realtime

技術仕様書:リアルタイム・トレンド解析システム

本ページは、単なるデモではありません。サーバーサイドスクレイピング、DOM解析、そしてAPI設計の完全な実装例を示す技術資料です。 X(旧Twitter)の公式APIに依存せず、公開されているウェブ情報からトレンドを抽出・構造化するエンジンの全貌を公開します。

Target

twittrend.jp (Trend Aggregator)

Method

DOMXPath Parsing / PHP 8.x

1

コア・アーキテクチャ

このシステムは、サーバーサイド(PHP)で外部サイトのHTMLを取得し、必要な情報だけを抽出してJSON APIとしてフロントエンドに提供する「バックエンド・フォー・フロントエンド(BFF)」パターンを採用しています。

// Architecture Logic Flow
Browser JS (Fetch)
-- request -->
Gateway API PHP Script
-- scraping -->
Target Site Raw HTML
2

ソースコード完全解説

本番環境で実際に稼働している api/trends.php の全コードです。エラーハンドリングやUser-Agent偽装など、安定したスクレイピングに必要な要素が網羅されています。

api/trends.php
<?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 で一般的なブラウザの署名をヘッダーに付与することで、これを回避しています。