site:domain 搜索结果统计。<?php
function httpGet(string $url, array $headers = []): string
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
CURLOPT_HTTPHEADER => array_merge([
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8',
], $headers),
]);
$content = curl_exec($ch);
if ($content === false) {
throw new \RuntimeException('cURL error: ' . curl_error($ch));
}
curl_close($ch);
return $content;
}
<?php
function getBaiduIndex(string $domain): array
{
$url = "https://www.baidu.com/s?wd=site:" . urlencode($domain);
$html = httpGet($url);
// 收录量:百度页面结构常变,以下正则需根据实时 HTML 调整
// 典型片段:找到相关结果数约 1,234 个
if (preg_match('/找到相关结果数[约\s]*([\d,]+)\s*个/ui', $html, $m)) {
$total = (int)str_replace(',', '', $m[1]);
} elseif (preg_match('/该网站共有([\d,]+)个网页被百度收录/ui', $html, $m)) {
$total = (int)str_replace(',', '', $m[1]);
} else {
$total = 0;
}
// 快照时间:搜索结果首条的快照链接
// 典型片段:2024-01-15
$snapshot = '暂无快照';
if (preg_match('/(\d{4}-\d{1,2}-\d{1,2})<\/span>/ui', $html, $m)) {
$snapshot = $m[1];
}
return [
'domain' => $domain,
'total' => $total,
'snapshot' => $snapshot,
'checked_at' => date('Y-m-d H:i:s'),
];
}
// 使用
print_r(getBaiduIndex('example.com'));
<?php
function getBaiduHotTop(int $limit = 10): array
{
// 官方 RSS:https://top.baidu.com/rss_xml.php?p=top10
$rssUrl = 'https://top.baidu.com/rss_xml.php?p=top' . ($limit <= 10 ? 10 : 50);
$xml = httpGet($rssUrl);
// 修复实体引用 & -> &
$xml = str_replace('&', '&', $xml);
// 简单 XML 解析
$doc = simplexml_load_string($xml);
if (!$doc) return [];
$keywords = [];
// 结构:关键词
foreach ($doc->xpath('//table/tbody/tr/td/a') as $a) {
$kw = trim((string)$a);
if ($kw) $keywords[] = $kw;
if (count($keywords) >= $limit) break;
}
return $keywords;
}
print_r(getBaiduHotTop(20));
<?php
// cron.php 每天 02:00 执行
require 'db.php'; // PDO 实例 $pdo
$domain = 'example.com';
$data = getBaiduIndex($domain);
$stmt = $pdo->prepare('INSERT INTO baidu_index (domain, total, snapshot, checked_at) VALUES (?, ?, ?, ?)');
$stmt->execute([$data['domain'], $data['total'], $data['snapshot'], $data['checked_at']]);
// 热搜榜单独存表
$hot = getBaiduHotTop(50);
foreach ($hot as $rank => $kw) {
$pdo->prepare('INSERT INTO baidu_hot (keyword, rank, date) VALUES (?, ?, CURDATE())')
->execute([$kw, $rank + 1]);
}
| 风险 | 对策 |
|---|---|
| 频率过高被封 IP | 间隔 ≥ 30 秒,使用代理池轮换 IP,设置随机 User-Agent |
| 页面结构变更导致正则失效 | 增加选择器容错(多正则备选)、监控采集成功率、异常报警 |
| 法律合规 | 遵守 robots.txt、百度服务条款,仅采集公开聚合数据,不存储用户隐私,频率控制在合理范围 |
| 验证码拦截 | 遇到验证码页面自动暂停、人工介入或引入打码平台(不推荐) |
百度移动端/新版 PC 页面大量 JS 渲染,正则难以提取。推荐方案:
# Node.js + Puppeteer 微服务
const puppeteer = require('puppeteer');
async function fetchBaidu(url) {
const browser = await puppeteer.launch({headless: true, args: ['--no-sandbox']});
const page = await browser.newPage();
await page.setUserAgent('Mozilla/5.0 ...');
await page.goto(url, {waitUntil: 'networkidle2'});
const html = await page.content();
await browser.close();
return html;
}
// PHP 通过 HTTP 调用该微服务获取渲染后 HTML
百度数据采集核心在于:稳健的 HTTP 客户端(cURL + 伪造头) + 容错的解析策略(多正则/XPath 备选) + 合规的频率控制。热搜榜优先用官方 RSS,收录/快照建议配合 Headless 渲染提高成功率。所有采集数据仅供内部分析,严禁商业倒卖或大规模并发冲击目标站点。