百度新闻开放协议是一套由百度制定的站点新闻推送规范,本质上是一种定制化的XML格式文档。站点通过输出符合该协议的XML文件,可以让百度新闻爬虫更高效地抓取站点产生的新闻内容,从而获得新闻源收录与展示机会。理解这套协议,核心在于搞清楚它强制要求的字段、可选的辅助字段,以及文档本身的编码和结构约束。

一、百度新闻开放协议的基础结构
协议文档的最外层必须使用rn_list作为根节点,这与常见的RSS使用rss或feed不同。在根节点内部,每一个新闻条目都被包裹在item标签中。一个文档可以包含多个item,但建议单次推送不超过100条,避免文件过大影响抓取。
每个item内在协议里被明确要求必须包含四个基础字段:title表示新闻标题,link为新闻详情页绝对地址,description是内容摘要,pubDate则是发布时间,格式需符合RFC822。除此之外,category、author、source以及image等属于可选标签,但填写后有助于提升新闻质量评分。
1.1 基础字段示例说明
下面给出一个最小可用的item结构示例,注意所有尖括号在真实文件中不需要转义,此处仅为展示标签名称:
<item> <title>本地新区发布产业发展规划</title> <link>https://ipipp.com/news/123.html</link> <description>昨日新区公布了未来五年的产业落地细则</description> <pubDate>Mon, 12 May 2025 09:30:00 GMT</pubDate> </item>
上面的pubDate使用了GMT时间,若使用本地时区也可以,但务必保证格式能被解析。很多新手容易把时间写成“2025-05-12 09:30:00”,这种格式在协议里属于不规范写法,会导致节点被忽略。
二、使用PHP生成协议XML文档
手工拼接XML字符串极易出现标签未闭合或特殊字符未转义的问题。更稳妥的做法是利用语言内置的XML或数组序列化工具来生成。以PHP为例,可以先将新闻数据整理成关联数组,再通过SimpleXMLElement对象写入节点。
在写入description等可能含有&、<等符号的字段时,PHP的XML扩展会自动处理转义,我们不必手动替换。以下示例展示了一个完整的文档生成过程,包含根节点与两个新闻条目。
<?php
// 构造新闻数据
$newsList = array(
array(
'title' => '示范区落地十项新规',
'link' => 'https://ipipp.com/news/001.html',
'description' => '本次发布的规则涉及税收与人才引进',
'pubDate' => 'Mon, 12 May 2025 08:00:00 GMT'
),
array(
'title' => '行业峰会将于下月召开',
'link' => 'https://ipipp.com/news/002.html',
'description' => '预计超过五百家企业参与本次大会',
'pubDate' => 'Mon, 12 May 2025 10:20:00 GMT'
)
);
// 创建根节点
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><rn_list></rn_list>');
foreach ($newsList as $item) {
$node = $xml->addChild('item');
$node->addChild('title', $item['title']);
$node->addChild('link', $item['link']);
$node->addChild('description', $item['description']);
$node->addChild('pubDate', $item['pubDate']);
}
// 输出并设置头信息
header('Content-Type: text/xml; charset=utf-8');
echo $xml->asXML();
?>
这段代码首先定义了数据数组,然后实例化SimpleXMLElement并声明编码为UTF-8。循环里使用addChild方法添加子节点,能有效规避手写字符串拼接引起的结构错误。最后通过asXML输出,浏览器或爬虫拿到的就是标准协议文档。
2.1 编码与转义注意事项
协议明确要求文档编码必须是UTF-8,不能是GBK或其他格式。如果数据库取出的是GBK字符串,需要先使用iconv或mb_convert_encoding转为UTF-8再写入。另外,新闻标题里若含有<这类字符,扩展会自动转为<,我们不应提前手动转义,否则会出现双重转义变成&lt;。
还有一个容易忽略的点:link里的地址必须是完整绝对路径,不能写相对路径如/news/001.html。百度爬虫不会自动补全域名,相对路径会被判定为无效链接从而丢弃该条新闻。
三、Python生成方式与验证
如果站点后端使用Python,同样可以用标准库xml.etree.ElementTree来构建。思路与PHP一致,先建根节点再循环添加子元素,最后序列化输出。Python的优势在于类型清晰,且在数据处理脚本中更容易对接数据库查询的结果集。
生成之后,建议使用xmllint命令或在线XML校验工具检查文档是否良构。只有通过了良构校验,且字段符合协议约束,提交到百度站长平台的新闻推送接口才能被正确识别。
import xml.etree.ElementTree as ET
root = ET.Element('rn_list')
items = [
{'title': '新能源补贴标准更新', 'link': 'https://ipipp.com/news/101.html',
'description': '财政部调整了补贴退坡节奏', 'pubDate': 'Mon, 12 May 2025 11:00:00 GMT'}
]
for data in items:
item = ET.SubElement(root, 'item')
ET.SubElement(item, 'title').text = data['title']
ET.SubElement(item, 'link').text = data['link']
ET.SubElement(item, 'description').text = data['description']
ET.SubElement(item, 'pubDate').text = data['pubDate']
tree = ET.ElementTree(root)
tree.write('baidu_news.xml', encoding='utf-8', xml_declaration=True)
上述脚本会在当前目录生成baidu_news.xml文件。我们在write时指定了encoding='utf-8'与声明头,确保文件开头带有正确的XML声明。实际部署时,可改为直接通过Web框架返回响应体,而非落盘成文件。
四、常见错误与排查思路
第一种常见错误是根节点名称拼写错误,例如写成rnlist或rn_List,爬虫会因无法识别结构而不解析。第二种是缺少必填字段,特别是pubDate漏写,会导致整条item被跳过。第三种是HTML标签未清理,把含
正文的完整HTML塞进description,虽然协议未严禁,但容易因内部未转义引号引发结构断裂。
排查时,可先抓取自己输出的XML地址,用命令行执行curl查看原始响应,确认头部Content-Type为text/xml且 body 以<?xml开头。若发现乱码,优先检查服务端是否二次输出了BOM头或混用了编码函数。把这些细节处理妥当,百度新闻开放协议XML文档的制作就不再是难题。