ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

必应搜索PHP源码拆解:无API Key实现网页搜索与结果解析

必应搜索PHP源码拆解:无API Key实现网页搜索与结果解析 简介这是一份基于PHP实现的必应网页搜索程序v1.0源码面向具备PHP基础、希望学习第三方搜索API集成的Web开发者与初学者。程序通过PHP中间层与微软Bing搜索API通信完成请求发送、响应解析与结果展示可用于搭建自定义搜索页面或作为API调用练手项目。压缩包共27个文件约148KB包含4个PHP核心脚本配置、搜索入口与请求处理、5个JavaScript交互脚本、3个CSS样式表以及png、gif、jpg等界面素材和xml、txt说明文档结构紧凑、便于阅读。目前已有256人学习下载。解压后可参考说明文档理解配置项与API密钥设置方式学习cURL请求、JSON/XML解析、搜索表单与结果页渲染的完整链路并可按需扩展缓存或数据库记录功能是入门搜索接口开发的实用参考。1. 一个 PHP 单文件搜索页为什么还有人愿意拆必应网页搜索的 PHP 程序源码听起来像是个“套壳页面”——前端一个输入框后端拼个 URL 跳过去就完事。但真正拆过这类源码的人知道事情没这么简单。必应官方并不提供公开的网页搜索 API 给个人开发者直接调用所以这类 PHP 程序的核心价值在于它用服务端抓取或接口模拟的方式把必应搜索结果页的数据取回来再在自己的页面上重新渲染。你拿到的是一个完整的、可部署的搜索中间层。这份 v1.0 源码适合三类人一是想学 PHP 做搜索聚合的开发者二是需要在自己的站内嵌入搜索能力但不想依赖第三方 JS SDK 的站长三是想研究必应搜索结果页 DOM 结构和参数规律的技术爱好者。它解决的核心问题是让你在不申请任何 API Key 的情况下通过 PHP 后端完成一次完整的必应搜索请求并解析结果。下面我从代码结构、部署流程、参数调优到踩坑记录把这套源码拆开讲清楚。2. 源码结构与请求链路从入口文件到结果渲染2.1 目录骨架与文件职责拿到压缩包解压后常见的目录结构大致如下不同版本可能略有差异但核心文件不会少bing-search-php/ ├── index.php # 入口文件渲染搜索框和结果页 ├── search.php # 核心搜索逻辑接收关键词并请求必应 ├── config.php # 配置项请求头、超时、结果数量等 ├── lib/ │ ├── Request.php # HTTP 请求封装类 │ └── Parser.php # HTML 解析类提取搜索结果 ├── assets/ │ ├── style.css # 页面样式 │ └── script.js # 前端交互搜索建议、分页等 └── cache/ # 搜索结果缓存目录需可写index.php负责展示搜索界面表单提交到search.php。search.php接收q参数关键词调用lib/Request.php向必应发起请求拿到 HTML 后用lib/Parser.php提取标题、链接、摘要最后输出到页面。config.php里通常定义了请求头中的 User-Agent、Accept-Language、超时时间、每页结果数等。注意cache/目录必须有写入权限否则缓存功能会静默失败每次搜索都重新请求速度会明显变慢。2.2 请求构造必应搜索 URL 的参数拆解必应网页搜索的基础 URL 是https://www.bing.com/search核心参数如下参数含义常用值q搜索关键词URL 编码后的字符串count每页结果数10 / 20 / 30first结果偏移量1, 11, 21...FORM来源标识可自定义不影响结果setlang界面语言zh-Hans / encc国家/地区CN / US源码里search.php构造请求的典型写法// search.php 核心请求片段 $keyword isset($_GET[q]) ? trim($_GET[q]) : ; $page isset($_GET[page]) ? max(1, intval($_GET[page])) : 1; $count 10; $first ($page - 1) * $count 1; $params http_build_query([ q $keyword, count $count, first $first, setlang zh-Hans, cc CN, ]); $url https://www.bing.com/search? . $params; $ch curl_init(); curl_setopt_array($ch, [ CURLOPT_URL $url, CURLOPT_RETURNTRANSFER true, CURLOPT_FOLLOWLOCATION true, CURLOPT_TIMEOUT 10, CURLOPT_HTTPHEADER [ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept-Language: zh-CN,zh;q0.9, ], ]); $html curl_exec($ch); curl_close($ch);这段代码的逻辑很直白拼参数、发请求、拿 HTML。first参数控制分页偏移第 1 页是 1第 2 页是 11以此类推。setlang和cc影响返回结果的地区和语言偏好如果你做的是中文站保持zh-Hans和CN就行。CURLOPT_TIMEOUT设 10 秒是常见做法必应响应通常很快超过 10 秒基本是网络问题。2.3 HTML 解析从结果页提取结构化数据拿到 HTML 后解析是第二个关键步骤。必应搜索结果页的结果条目通常包裹在li classb_algo标签里标题在h2a中摘要在p或div classb_caption中。源码里Parser.php一般用 DOMDocument 或正则来提取// lib/Parser.php 解析片段 $dom new DOMDocument(); libxml_use_internal_errors(true); $dom-loadHTML(mb_convert_encoding($html, HTML-ENTITIES, UTF-8)); $xpath new DOMXPath($dom); $items $xpath-query(//li[contains(class, b_algo)]); $results []; foreach ($items as $item) { $titleNode $xpath-query(.//h2/a, $item)-item(0); $linkNode $xpath-query(.//h2/a/href, $item)-item(0); $descNode $xpath-query(.//p, $item)-item(0); if ($titleNode $linkNode) { $results[] [ title trim($titleNode-textContent), url trim($linkNode-nodeValue), desc $descNode ? trim($descNode-textContent) : , ]; } }用 DOMXPath 比正则稳因为必应的 HTML 结构偶尔会调整但b_algo这个 class 名多年没变过。libxml_use_internal_errors(true)是为了吞掉 HTML 不规范导致的警告否则页面上会冒出一堆 warning。解析出来的$results数组直接交给index.php渲染即可。提示如果解析结果为空先检查$html是否真的包含b_algo有时候必应会返回验证页或空结果页这时候需要检查请求头是否被识别为爬虫。3. 部署与调试从零跑通一次搜索3.1 环境准备与配置项调整这套源码对环境要求不高PHP 7.0 以上就能跑但建议用 PHP 7.4 或 8.x因为 8.x 对 DOMDocument 的性能有优化。需要开启的扩展curl、dom、mbstring、json。如果你用的是宝塔面板或 phpstudy这些扩展默认都有。部署步骤把源码解压到网站根目录或子目录确保cache/目录可写chmod 755或777视服务器用户而定修改config.php中的超时时间和缓存开关浏览器访问index.php输入关键词测试config.php里几个值得关注的配置// config.php 关键配置 return [ timeout 10, // 请求超时秒数 cache_enable true, // 是否开启缓存 cache_time 3600, // 缓存有效期秒 per_page 10, // 每页结果数 user_agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, ];cache_time设 3600 表示同一关键词一小时内只请求一次必应后续直接读缓存文件。这对个人站来说够用但如果你做的是新闻类搜索建议降到 300 秒。per_page不要超过 30必应对单页结果数有限制超过 30 可能会被截断或触发验证。3.2 搜索请求的完整调试流程部署完第一次访问大概率会遇到“搜索结果为空”或“页面报错”。我一般按这个顺序排查第一步在search.php里把$html打印出来看看到底返回了什么。如果是一堆 JS 或者验证页面说明请求头被识别了。这时候换一个更真实的 User-Agent加上Accept和Referer头。第二步检查curl_exec的返回值。如果返回false用curl_error($ch)看具体错误。常见的是 SSL 证书问题加一行CURLOPT_SSL_VERIFYPEER false可以临时绕过但生产环境不建议。第三步如果$html正常但解析为空把$html保存成文件用浏览器打开搜索b_algo看是否存在。如果不存在说明必应改了结构或者返回了不同版本的结果页。// 调试用保存原始 HTML 到文件 file_put_contents(__DIR__ . /debug_ . md5($keyword) . .html, $html);这个调试代码我每次接手新的搜索类项目都会加跑通后再删掉。它能帮你省下大量猜测时间。3.3 分页与结果数量的参数边界分页逻辑看似简单但有几个边界要注意。first参数从 1 开始每页递增per_page。但必应对first有上限通常最多到 200 左右再往后翻结果质量会急剧下降甚至返回空。所以你的分页组件不要做成无限翻页建议最多显示 10 页。另外count参数虽然可以设到 50但实际返回的结果数往往少于你请求的数量。必应会根据查询意图动态调整有些关键词只返回 8 条有些返回 20 条。你的解析代码要能处理“结果数少于预期”的情况不要写死循环。注意如果你在search.php里用了header(Location: ...)做跳转记得在跳转前完成所有数据处理否则缓存写入会被中断。4. 避坑与常见问题那些让你白忙半天的细节4.1 请求被重定向到验证页现象$html里没有b_algo而是一段 JavaScript 或者“请验证你是人类”的提示。原因必应对频繁请求或异常请求头会返回验证页。常见触发条件同一 IP 短时间内大量请求、User-Agent 为空或过于简单、缺少Accept-Language头。解决在CURLOPT_HTTPHEADER里补全Accept、Accept-Language、Referer三个头。如果还是不行降低请求频率并在cache层做更激进的缓存策略。我一般会把cache_time调到 7200 秒牺牲实时性换稳定性。4.2 中文关键词乱码现象搜索中文关键词时结果页标题和摘要显示为乱码。原因必应返回的 HTML 编码可能是 UTF-8但DOMDocument::loadHTML默认按 ISO-8859-1 处理导致中文被错误解码。解决在loadHTML之前做编码转换或者直接在 HTML 字符串前面加meta charsetUTF-8$html meta http-equivContent-Type contenttext/html; charsetutf-8 . $html; $dom-loadHTML($html);这行代码看着不起眼但少了它中文搜索结果全是问号。4.3 缓存目录权限导致静默失败现象搜索功能正常但每次刷新页面速度都一样慢缓存文件没有生成。原因cache/目录没有写入权限file_put_contents返回false但代码里没有做错误处理所以静默失败。解决在缓存写入处加判断$cacheFile __DIR__ . /cache/ . md5($keyword) . .json; if (!is_dir(dirname($cacheFile))) { mkdir(dirname($cacheFile), 0755, true); } if (file_put_contents($cacheFile, json_encode($results)) false) { error_log(Cache write failed: . $cacheFile); }同时检查cache/目录的所属用户是否和 PHP 运行用户一致。Linux 下ps aux | grep php可以看到运行用户然后chown一下就行。4.4 分页参数被忽略现象点击第二页结果和第一页一样。原因search.php里读取page参数时用了$_GET[page]但前端分页链接没有把page传过去或者传了但被intval成了 0。解决检查前端分页链接的构造确保page参数正确拼接。后端用max(1, intval($_GET[page] ?? 1))做兜底。另外first的计算要用($page - 1) * $count 1不要写成$page * $count否则第一页会从第 11 条开始。4.5 PHP 8 下的兼容性问题现象在 PHP 8.0 以上环境运行时页面报Deprecated或TypeError。原因这套源码 v1.0 可能是在 PHP 7.x 下写的PHP 8 对部分函数签名和类型检查更严格。常见问题curl_close在 PHP 8 中不再是必须的但也不报错mb_convert_encoding的第二个参数在 PHP 8.2 后有所调整。解决把mb_convert_encoding($html, HTML-ENTITIES, UTF-8)改成mb_convert_encoding($html, UTF-8, UTF-8)或者直接用htmlspecialchars处理。如果报错在DOMDocument相关代码升级到 PHP 8.1 以上通常会自动解决大部分兼容问题。5. 进阶技巧让搜索页跑得更稳的几个习惯5.1 用多组 User-Agent 轮换降低被识别概率单一 User-Agent 用久了容易被必应标记。我一般会在config.php里放一个数组每次请求随机取一个$agents [ Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15, Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36, ]; $ua $agents[array_rand($agents)];配合cache_time拉长到 3600 秒以上基本可以做到一天只发几十次请求被验证的概率极低。5.2 结果去重与域名过滤必应搜索结果里经常出现同一域名的多条记录。如果你做的是聚合展示去重能提升体验$seen []; $unique []; foreach ($results as $r) { $host parse_url($r[url], PHP_URL_HOST); if (!isset($seen[$host])) { $seen[$host] true; $unique[] $r; } } $results $unique;这段代码按域名去重每个域名只保留第一条结果。如果你还想过滤掉某些站点加一个黑名单数组在循环里continue掉就行。5.3 验证搜索是否真正生效的检查清单每次部署完或修改代码后我习惯走一遍这个清单检查项预期结果不通过时看哪里搜索框提交后 URL 带q参数地址栏出现?q关键词index.php表单 method 和 action页面显示至少 5 条结果标题、链接、摘要齐全Parser.php的 XPath 查询翻到第二页结果不同第 11 条开始search.php的first计算同一关键词第二次搜索变快缓存文件生成cache/权限和cache_enable中文关键词不乱码标题正常显示loadHTML前的编码声明这个清单我每次改完搜索类项目都会跑一遍五分钟内能定位到 90% 的问题。从那以后我每次部署新的搜索源码都强制先跑一遍这个检查表再去做样式和交互。希望帮到你。本文还有配套的精品资源点击获取
返回列表