DedeCMS怎么用宝塔做百度自动推送?baiduapi.php脚本加定时任务

DedeCMS怎么用宝塔做百度自动推送?baiduapi.php脚本加定时任务
张文保 更新 27 分钟阅读 5,565 阅读
本文目录
  1. 为什么 DedeCMS 站点必须自己写推送脚本
  2. 普通收录 API 的配额规则与备案差异
  3. DedeCMS 数据库里要查的三张表
  4. 能直接用的 baiduapi.php 完整脚本
  5. 逐段拆解:脚本里每个细节都不是装饰
  6. 用 DedeCMS 自己的 dsql 而不是新建 PDO
  7. 时间戳取当日范围而不是相对秒数
  8. arcrank = 0 过滤未审核稿
  9. typedir 必须做 {cmspath} 替换
  10. 已推送去重
  11. 日志落地到 data/ 目录
  12. 宝塔计划任务的细致配置
  13. 推送结果监控:怎么知道推送真的生效
  14. 常见错误码与排错
  15. 进阶:和 sitemap、indexnow 一起用
  16. 安全加固:避免推送脚本被外人触发
  17. 额外细节:DedeCMS 列表页与详情页 URL 一致性
  18. 常见问题解答
  19. API 推送和主动推送有什么区别?
  20. 推送脚本会不会和 DedeCMS 自身的 SEO 插件冲突?
  21. 为什么我的 success 总是 0,但 remain 又在减?
  22. 每天推送上限是多少?没备案的站点会被惩罚吗?
  23. 计划任务说执行成功,但日志里看不到推送记录怎么办?
  24. 能不能改成实时推送,文章一发布就推?
  25. 脚本能用在 DedeCMS V5.6、V5.7、V5.8 之间吗?
  26. 写在最后
  27. 权威参考资料
手把手讲清DedeCMS的百度普通收录API推送。本文给能直接用的baiduapi.php完整脚本——从archives与arctype三表join取当日链接、占位符替换、curl POST到百度接口,再叠加宝塔每天定时任务、success与remain字段监控、错误码排错,讲和sitemap与indexnow的协同、避免推送脚本被外人触发的安全加固,是套能复用三年的方案。

保哥这两年帮人做织梦 DedeCMS 站点的 SEO 收尾工作,常被问到一个看似很基础但落地很麻烦的问题:怎么让百度第一时间抓到 DedeCMS 当天发布的新文章?答案不止是把 sitemap.xml 挂到搜索资源平台那么简单,真正能压缩百度收录时间的做法是把"普通收录 API 推送"接到 DedeCMS 的发布流程里,让每一篇文章一发布就被推送出去。本文把整条链路从原理、脚本、宝塔计划任务、监控、错误码到日常排错全部摊开来讲,是我自己在二十多个 DedeCMS 站点上反复跑过、稳定使用三年以上的方案。

为什么 DedeCMS 站点必须自己写推送脚本

百度对 DedeCMS 这类相对老旧的 CMS 没有任何官方插件,搜索资源平台里 WordPress 的"百度搜索推送管理"只能装在 WP 上,DedeCMS 用户只能选这三条路:

  1. 纯手工提交:每天打开站长后台,把当天链接粘到普通收录的"手动提交"框里。低于 50 篇还能忍,超过这个量就完全不现实。
  2. sitemap.xml 自动提交:把 sitemap 地址挂到普通收录的"sitemap"模块。优点是不用脚本,缺点是百度对 sitemap 的抓取节奏完全由它自己控制,热门站可能 30 分钟一次,冷门站可能 24 小时一次,对刚发布的内容并不及时。
  3. API 推送:拿到 token 之后,自己用 curl 把 URL POST 到 http://data.zz.baidu.com/urls。响应是即时的,被推送的链接会进入百度的优先抓取队列,平均抓取时间从 sitemap 的小时级压到分钟级。

三种方式可以叠加用,并不冲突。但要把"发布即推送"做出来,只有第三种能做到。下面整篇都是围绕第三条展开。

普通收录 API 的配额规则与备案差异

百度搜索资源平台对 API 推送有明确的每日配额。配额值不是固定的 10 万,它跟两个变量挂钩:

  • 站点权重等级:搜索资源平台后台"站点信息"里能看到一个隐藏字段叫"接口推送配额"。新站普遍是 5000~10000 条/日,做了半年以上、有自然流量进来的站点能到 20000~50000,权重 5+ 的优质站点上限是 100000。
  • 是否完成 ICP 备案:未备案站的配额会被压到正常值的 30%~50%,并且部分推送会直接被丢弃。这是在 2023 年百度内部一次反垃圾调整后开始严格执行的,做国内站不要心存侥幸。

实测数据:保哥手上一个 DedeCMS 旅游站,备案前每日配额显示 8000,实际能成功推送的不到 5000;备案下来之后第二周配额自动跳到 20000,全量都能推成功。所以"备案值不值"在这个语境下答案是肯定的。

DedeCMS 数据库里要查的三张表

DedeCMS 把一篇文章拆在三张表里存,要拿到完整的发布 URL 必须 join:

  • dede_archives:主表,存 id、typeid、title、pubdate、senddate 等通用字段。
  • dede_arctype:栏目表,存 id、typename、typedir、ispart 等。typedir 是关键,它决定 URL 路径前缀,可能含 {cmspath} 占位符。
  • dede_addonarticle:附属表,存正文 body、写法 redirecturl、自定义字段等,对推送来说一般用不到,但做"只推送有正文的文章"时需要它。

三张表里 typedir 的写法多半是 {cmspath}/news{cmspath}/product/zhuangbei{cmspath} 默认是空字符串(DedeCMS 系统参数 cfg_cmspath),但如果站点装在二级目录下例如 /cms,这个值就会是 /cms。脚本里必须把 {cmspath} 替换成实际值再拼接 URL,否则推过去的全是带占位符的非法链接。

能直接用的 baiduapi.php 完整脚本

我现在线上跑的版本经过几轮迭代,比网上流传的最简版多了三块:错误日志、推送结果落地、已推送去重。完整代码:

<?php
/**
 * DedeCMS 百度普通收录 API 自动推送脚本
 * 放置位置:网站根目录 /baidu_push.php
 * 调用方式:宝塔计划任务每天 23:50 访问该 URL
 *
 * 依赖:dede/include/common.inc.php
 */
require_once dirname(__FILE__) . '/include/common.inc.php';

// ========== 配置区 ==========
$siteUrl   = 'https://www.zhangwenbao.com';
$apiToken  = '替换为你自己的 token';
$apiUrl    = 'http://data.zz.baidu.com/urls?site=' . parse_url($siteUrl, PHP_URL_HOST) . '&token=' . $apiToken;
$logFile   = dirname(__FILE__) . '/data/baidu_push.log';
$pushedDb  = dirname(__FILE__) . '/data/baidu_pushed.txt';
$cmsPath   = $cfg_cmspath ? $cfg_cmspath : '';

// 取当天发布且尚未推送过的链接
$dayBegin = mktime(0, 0, 0);
$dayEnd   = mktime(23, 59, 59);

$query = "SELECT a.id, a.title, t.typedir, t.ispart
          FROM dede_archives a
          INNER JOIN dede_arctype t ON a.typeid = t.id
          WHERE a.arcrank = 0
            AND a.pubdate >= {$dayBegin}
            AND a.pubdate <= {$dayEnd}";

$dsql->Execute('push', $query);
$urls = [];
while ($row = $dsql->GetArray('push')) {
    $dir   = str_replace('{cmspath}', $cmsPath, $row['typedir']);
    $url   = $siteUrl . $dir . '/' . $row['id'] . '.html';
    $urls[] = $url;
}

// 去重:读取已推送清单
$pushed = file_exists($pushedDb)
    ? array_filter(array_map('trim', file($pushedDb)))
    : [];
$todo = array_values(array_diff($urls, $pushed));

if (empty($todo)) {
    file_put_contents($logFile, date('Y-m-d H:i:s') . " 无新链接需要推送\n", FILE_APPEND);
    exit('no new url');
}

// 调用百度推送接口
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL            => $apiUrl,
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_POSTFIELDS     => implode("\n", $todo),
    CURLOPT_HTTPHEADER     => ['Content-Type: text/plain'],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr  = curl_error($ch);
curl_close($ch);

// 落地日志与已推送清单
$logLine = date('Y-m-d H:i:s')
    . " count=" . count($todo)
    . " http={$httpCode}"
    . " resp=" . trim($response)
    . ($curlErr ? " err={$curlErr}" : '')
    . "\n";
file_put_contents($logFile, $logLine, FILE_APPEND);

if ($httpCode == 200) {
    $result = json_decode($response, true);
    if (!empty($result['success'])) {
        file_put_contents($pushedDb, implode("\n", $todo) . "\n", FILE_APPEND);
        echo 'OK pushed ' . $result['success'] . " urls\n";
    } else {
        echo "FAIL " . $response . "\n";
    }
} else {
    echo "HTTP {$httpCode} error\n";
}

逐段拆解:脚本里每个细节都不是装饰

这段代码看起来很长,但每一行都对应一个曾经踩过的坑。

用 DedeCMS 自己的 dsql 而不是新建 PDO

很多教程让你用 mysqli 或 PDO 直接连 DedeCMS 数据库,这在调试时方便,但在正式环境有两个问题:一是密码要硬编码到 baidu_push.php,泄露风险高;二是 DedeCMS 的 GBK/UTF-8 站点编码差异需要手动处理。直接 require include/common.inc.php 复用 DedeCMS 的 $dsql 全局对象,编码、字符集、连接池都自动解决。

时间戳取当日范围而不是相对秒数

原始版本里很多人写 pubdate > time() - 86400,意思是"过去 24 小时"。这个写法的问题是:如果计划任务定在 23:50 跑,就会把昨天 23:50 之后到今天 23:50 之前的内容推一遍;但如果某天计划任务延迟了 30 分钟,就会漏掉前一天 23:50~00:20 的发布。用 mktime(0,0,0)mktime(23,59,59) 锁住"自然日",跑得早跑得晚都是同一批数据。

arcrank = 0 过滤未审核稿

DedeCMS 的 arcrank 字段:0 是开放浏览,-1 是待审核,>0 是会员等级阅读权限。如果你的站点开了"投稿要审核",没加 arcrank = 0 这个过滤条件,就会把待审稿的草稿链接也推给百度,返回的是 404,相当于亲自给自己制造死链

typedir 必须做 {cmspath} 替换

这是被忽略最多的一行。线上看到过一个站,所有推送链接长这样:https://example.com{cmspath}/news/123.html。百度照样收,但收的全是 404。最后才发现该站装在 /site 二级目录里,cfg_cmspath/site,但脚本作者没替换占位符,整月配额白白浪费。

已推送去重

这是脚本对外不太显眼但很重要的一块。baidu_pushed.txt 文件按行存所有已推送 URL。每次跑都先做 array_diff,避免相同链接当天反复推送。百度文档没有明说重复推送会扣配额,但实测上:同一 URL 一周内推第二次以上的,会被记进 not_same_site 或干脆静默丢弃。该文件长期累积,每两个月可以人工清空一次,或者改成只保留最近 60 天。

日志落地到 data/ 目录

data/ 而不是网站根目录是因为 DedeCMS 官方默认 nginx 规则里 data/ 不允许 PHP 执行,但允许写入和读取。日志放这里既能写又不会被外网当作脚本访问。

宝塔计划任务的细致配置

宝塔的"任务类型"四选一里,这种场景应该用"访问 URL",因为它走的是宝塔自己的 curl,不依赖外部 cron 配置 PATH。具体步骤:

  1. 登录宝塔面板,左侧"计划任务"。
  2. 点"添加任务"。任务类型选 访问URL
  3. 任务名称填一个有辨识度的:DedeCMS 百度推送 - zhangwenbao.com
  4. 执行周期:每天 23:50。理由后面有详述。
  5. URL 地址填 https://www.zhangwenbao.com/baidu_push.php?key=xxxxkey 是你脚本里加的访问 token,避免被外网随便触发。
  6. 勾上"日志保留"。宝塔每次执行的输出会被记录,方便事后核对。

为什么是 23:50?我在三类时间点都跑过对比:早上 6 点跑、下午 14 点跑、晚上 23:50 跑。前两个时间点都会漏掉之后发布的文章,第二天才推;23:50 跑能把当天 0~23:50 发布的全部捕捉到,剩下 23:50~00:00 这十分钟的发布留给次日的当天范围(因为 mktime 锁的是自然日)。如果你站点发文集中在白天,可以再多挂一个早晨 8:00 的任务做兜底。

推送结果监控:怎么知道推送真的生效

百度 API 的响应 JSON 长这样:

{
  "remain": 4985,
  "success": 12,
  "not_same_site": [],
  "not_valid": []
}

四个字段的实战含义:

  • remain:当天剩余配额。建议在脚本里把它打印到日志,连续几天 remain 接近 0 就说明配额吃满,需要去后台看看是不是申请提配额。
  • success:本次推送成功条数。这个数字应该等于你 POST 上去的 URL 数。如果小于,说明有部分链接被丢弃。
  • not_same_site:URL 域名跟 token 绑定的域名不一致。最常见原因是带 www 和不带 www 的差异、http 和 https 混用。
  • not_valid:URL 格式非法。常见于 typedir 没替换 {cmspath}、或者站点 URL 里有空格、中文。

除了 API 返回,还要去搜索资源平台后台看"普通收录—资源提交—API提交"的趋势曲线,正常情况是每天一个柱子,柱子高度对应当天推送量。如果连续一周柱子高度等于配额上限的 90%+,就该考虑申请提额或缩减提交范围。

常见错误码与排错

API 返回非 200 时按下面的对应表排查:

  • 400 site error:URL 里 site 参数和 token 不匹配,或 site 后没有跟域名。检查脚本里 parse_url 出来的 host 是不是真域名(不要把 IP 当 host)。
  • 401 token is not valid:token 错了,或者域名换了 token 没换。重新到搜索资源平台领新 token。
  • 403 over quota:今天配额吃满。明天再推。
  • 404 site not exists:搜索资源平台里这个站还没添加,或被删了。先在后台把站点加上。
  • 413 over body size:单次 POST 超过 5MB。把 todo 数组按 1000 一批切片再循环 push。
  • 500 internal error:百度自己的故障,过一小时再试。

实战中 90% 的失败都是 400 和 401 这两类,根因都是 token 或 site 配错。剩下 10% 是配额。脚本里把 httpCode 和 response 都写日志,排错时直接 grep 错误码即可。

进阶:和 sitemap、indexnow 一起用

很多人以为 API 推送上了 sitemap 就可以撤了。错。三种方式各管一段:

  • API 推送覆盖最近发布的内容,时效性强但每天有上限。
  • sitemap.xml覆盖全站存量,百度按自己节奏抓,能修复 API 漏掉的旧文章。
  • indexnow是必应、Yandex 系协议(百度 2024 年开始有限支持),可以补 API 之外的搜索引擎。

正确做法是三种全开。API 每天跑,sitemap 一次性挂上不再动,indexnow 在内容发布钩子里同步推。这套组合拳下来,新文章被百度收录的中位时间可以压到 10 分钟以内,而单靠 sitemap 通常要 4~24 小时。

安全加固:避免推送脚本被外人触发

baidu_push.php 一旦放到根目录,外人就能通过 URL 直接访问。这有两个风险:被恶意刷接口拖垮服务器、或者被刷成"接口访问异常"导致百度封 token。两条防护写到脚本最顶部:

// 1. 简单 key 校验
$expectedKey = 'p7Kb9vZmTw';
if (empty($_GET['key']) || $_GET['key'] !== $expectedKey) {
    header('HTTP/1.1 403 Forbidden');
    exit('forbidden');
}

// 2. IP 白名单(只允许本机或宝塔所在服务器调用)
$allowed = ['127.0.0.1', '::1', '你的宝塔出网IP'];
if (!in_array($_SERVER['REMOTE_ADDR'], $allowed, true)) {
    header('HTTP/1.1 403 Forbidden');
    exit('not allowed ip');
}

计划任务里 URL 必须带正确的 key 才能跑,外网误触都被 403 拦掉。如果你担心 key 在 URL 里被记进访问日志泄露,改成 POST 请求或者加 nginx 层 deny 都可以。

额外细节:DedeCMS 列表页与详情页 URL 一致性

有些站点把 DedeCMS 的"伪静态"开了一半:列表页用伪静态、详情页还是 plus/view.php?aid=123。这种情况下 typedir 拼出来的 URL 是伪静态形式,但实际访问是动态形式,百度收的是 plus/view.php?aid=123,跟你推送的不一致,最后表现为收录数远低于推送数。

解决办法:在 DedeCMS 后台"系统参数 - 性能选项"里把"是否使用伪静态"打开,并在 nginx 加上 dede 的伪静态规则。所有详情页都走 .html 之后,推送和实际页面就对得上了。

常见问题解答

API 推送和主动推送有什么区别?

百度官方在 2022 年统一了术语,现在文档里只有"普通收录"和"快速收录"。普通收录 API 推送就是本文讲的免费版本,每天有配额;快速收录 API 推送是给已经在搜索资源平台获得"快速收录"权限的优质站点用的,时效性更强(分钟级)但权限要单独申请,并不是所有站点都能开。本文脚本走的是普通收录,DedeCMS 站点直接拿来用。如果你的站点拿到了快速收录权限,把 apiUrl 换成 http://data.zz.baidu.com/urls?site=xxx&token=xxx&type=daily 即可。

推送脚本会不会和 DedeCMS 自身的 SEO 插件冲突?

不会。DedeCMS 自带的"百度推送"是在文章保存的 hook 里同步调一次 curl,本文方案是计划任务定时调一次。两者数据来源都是 dede_archives 表,重复推送被脚本里的 baidu_pushed.txt 去重过滤掉,只是日志条目会多一些。如果你已经装了 DedeCMS 的官方推送插件,可以保留,本脚本作为兜底兜住"插件偶发失败"的场景。

为什么我的 success 总是 0,但 remain 又在减?

这个组合的根因几乎都是"URL 域名带不带 www 与 token 绑定的域名不一致"。百度后台领 token 时填的是 www.zhangwenbao.com,脚本里 siteUrl 写的是 https://zhangwenbao.com,推过去之后被认为不是同站,进 not_same_site 数组,但配额已经扣了。改成完全一致的形式即可。如果你的站点既走 www 又走非 www,要在百度后台为两个域名分别申请 token 并分别推送。

每天推送上限是多少?没备案的站点会被惩罚吗?

普通收录的配额上限官方说是 10 万条/日,但实际是按站点权重等级动态分配,新站初始配额一般 5000~10000。未备案站点配额会被压到正常值的 30%~50%,且部分推送被丢弃。建议尽快完成 ICP 备案,备案下来后第二周左右配额会自动调高,对收录速度有肉眼可见的提升。

计划任务说执行成功,但日志里看不到推送记录怎么办?

第一步检查脚本是否有写入权限。data/baidu_push.log 这个文件如果不存在且 data 目录权限不允许 PHP 写入,file_put_contents 会静默失败。手动 touch data/baidu_push.log && chmod 666 data/baidu_push.log。第二步检查宝塔计划任务的"日志保留"选项是不是开了,开了之后宝塔后台能看到任务每次的标准输出。第三步确认 URL 带的 key 参数和脚本里 $expectedKey 一致,否则脚本第一行就 exit 了,根本走不到推送。

能不能改成实时推送,文章一发布就推?

可以。在 dede/archives_do.phpdede/article_add.php 里找到保存成功后的 hook 位置,加一段 curl 调用本文的 push 接口。但要注意:实时推送会让发布操作多一次外部 HTTP 请求,遇到百度服务慢的时候编辑器会卡几秒。建议异步触发:发布时只把 URL 写入一个待推送队列文件,由独立的计划任务每 5 分钟跑一次扫队列推送,编辑体验和推送时效可以兼得。

脚本能用在 DedeCMS V5.6、V5.7、V5.8 之间吗?

能。DedeCMS 三个主流版本里 dede_archives 和 dede_arctype 的字段命名一直保持兼容,arcranktypediridtypeidpubdate 五个字段在所有版本都存在。cfg_cmspath 在 V5.6 之前叫 cmspath,如果你跑在很老的版本里要改一下变量名。我自己跑过 V5.7.108 和 V5.8.1,脚本无需改动。

写在最后

把这套脚本接到你 DedeCMS 站点之后,第一周可以每天看一次日志,确认 success 数与发布数对得上、remain 配额是否合理。第二周开始基本就能放着不管。重点是任何 SEO 优化最终的判断标准只有一个:百度站长后台的"索引量"曲线是不是在涨。如果按本文做完一个月索引量没动,那不是推送的问题,要回到内容质量、站内结构、外链建设上找原因,光靠推送 API 推不出排名。

保哥这套思路目前在 zhangwenbao.com 之外还有十几个 DedeCMS 站在用,最长的一个跑了三年没出过故障。脚本本身很短,但里面每一行的取舍都是一次踩坑总结。读到这里你已经具备从零搭建 DedeCMS 百度自动推送的全部背景知识,剩下的就是把代码贴到自己站点跑通。遇到具体错误码不知道怎么处理时,回来翻第十节的对照表基本都能定位。

权威参考资料

FAQPage + Article AI 引用友好版

TL;DR · 60–80 字摘要 · 适用 ChatGPT / Perplexity / Gemini / 文心 引用

DedeCMS 没有官方百度推送插件,本文给出从数据库 join 到 baidu_push.php 全脚本、宝塔计划任务定时配置、推送结果监控、错误码排错的完整链路,让发布即推送在 DedeCMS 上落地。

关键实体 · Key Entities

  • 宝塔面板
  • 百度推送
  • 计划任务
  • 百度api
  • 百度提交
  • DedeCMS
  • 宝塔计划任务
  • 百度收录
  • 织梦CMS教程

引用元数据 · Citation Metadata

title:       DedeCMS怎么用宝塔做百度自动推送?baiduapi.php脚本加定时任务
author:      张文保 (Paul Zhang) — PatPat SEO 经理
url:         https://zhangwenbao.com/bt-baidu-api-dedecms-url.html
published:   2021-09-16
modified:    2026-06-01
source-type: First-hand expert commentary
language:    zh-CN
license:     CC BY-NC-SA 4.0 (要求保留原文链接与作者归属)
分享到
标签
版权声明

本文标题:《DedeCMS怎么用宝塔做百度自动推送?baiduapi.php脚本加定时任务》

本文链接:https://zhangwenbao.com/bt-baidu-api-dedecms-url.html

版权声明:本文原创,转载请注明出处和链接。许可协议: CC BY-NC-SA 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交