dede蜘蛛爬行插件:织梦站抓取频次控制与日志可观测方案
简介dede蜘蛛爬行插件是一款面向DEDECMS织梦网站管理员与SEO从业者的搜索引擎优化辅助工具用于模拟百度、谷歌、360等爬虫对站点进行抓取帮助定位死链、404错误、加载缓慢页面及内链结构问题并给出URL规范化与HTML代码优化建议适合需要提升收录与排名的中小站长使用。资源包共38个文件以27个php程序文件为核心配合2个js、2个css负责交互与样式1个sql用于数据表初始化另有5个gif图标和1个txt说明整体仅36KB结构轻量、便于上传部署。目前已有374人学习下载。通过抓取日志分析与模拟爬行报告读者可快速掌握站点抓取状况排查无效链接与重复URL优化内链权重传递从而改善搜索引擎友好度是DEDECMS站点日常SEO巡检的实用脚本工具。1. dede蜘蛛爬行插件为什么你的内容收录总卡在“抓取”这一步做站群或者内容站的朋友大概率遇到过这种场景后台明明更新了几十篇原创提交了地图外链也发了可搜索引擎的蜘蛛来是来了抓取频次却低得可怜日志里大片 404、503甚至同一篇文章被反复抓了七八次。问题往往不在内容质量而在蜘蛛到达你站点之后的“行走路径”没有被引导好。dede蜘蛛爬行插件就是围绕这个痛点做的一类扩展它挂在织梦DedeCMS体系上通过动态生成蜘蛛可识别的入口、控制抓取频次、记录爬行日志让搜索引擎的抓取行为从“随机游走”变成“按图索骥”。这套东西适合手里有织梦老站、内容量在几千到几十万级、又不想大动干戈重构的站长和优化工程师。接下来我会把它的原理、落地配置、参数调优和踩坑记录拆开讲让你看完能直接在自己的站上复现一套可观测、可干预的爬行引导方案。2. 蜘蛛爬行引导的底层逻辑与织梦挂载点选择2.1 蜘蛛是怎么“决定”抓哪条 URL 的搜索引擎蜘蛛的调度不是玄学它有一套明确的优先级队列。简单说蜘蛛拿到一个种子 URL 后会解析页面里的可抓链接放进待抓队列再根据历史抓取质量、页面更新频率、站点权重给每条 URL 打分。分数高的先抓分数低的往后排排太久就可能被丢弃。很多织梦站的问题在于列表页分页、标签页、搜索页生成了大量参数化 URL蜘蛛在这些低价值页面上消耗了预算真正的内容页反而排不上队。dede蜘蛛爬行插件要解决的第一件事就是把这些“抓取预算”重新分配——通过主动输出干净的 URL 列表、屏蔽无意义的动态参数入口让蜘蛛把精力花在内容页上。理解这一点后面所有配置才有判断依据你不是在“求”蜘蛛来而是在帮它做减法。2.2 为什么选织梦的 include 层做挂载织梦的架构里include/目录下的公共文件是每次请求都会加载的比如common.inc.php、extend.func.php。把爬行插件的核心逻辑挂在这里好处是不用改模板、不用动数据库结构升级织梦版本时冲突面也小。常见做法是在include/extend.func.php里注册几个自定义函数再在模板需要的位置调用。另一种做法是独立出一个include/spider_crawl.class.php在common.inc.php末尾按需引入。我一般倾向后者因为逻辑集中、方便加日志、出问题好回滚。挂载点选对了后面加规则、改频次、看日志都只是改一个文件的事不会牵一发动全身。2.3 最小可运行版本先让蜘蛛拿到一份干净入口在动手写完整插件前先做一个最小验证生成一份只包含内容页的入口列表看蜘蛛是否愿意抓。下面这段 PHP 放在织梦根目录通过访问触发输出纯文本 URL 清单。?php // spider_entry.php 最小入口生成器 // 引入织梦数据库配置路径按实际站点调整 require_once(dirname(__FILE__) . /data/common.inc.php); // 连接数据库 $dsn mysql:host{$cfg_dbhost};dbname{$cfg_dbname};charsetutf8; try { $pdo new PDO($dsn, $cfg_dbuser, $cfg_dbpwd); $pdo-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { // 出错时返回 503让蜘蛛稍后再来而不是拿到空列表 header(HTTP/1.1 503 Service Unavailable); exit(db error); } // 只取已审核、未删除、最近 30 天更新的文章 $sql SELECT arcid, senddate FROM #__archives WHERE arcrank 0 AND ismake 1 AND senddate UNIX_TIMESTAMP() - 86400 * 30 ORDER BY senddate DESC LIMIT 500; $stmt $pdo-query(str_replace(#__, $cfg_dbprefix, $sql)); $rows $stmt-fetchAll(PDO::FETCH_ASSOC); header(Content-Type: text/plain; charsetutf-8); foreach ($rows as $row) { // 织梦默认文章页规则按你站点实际伪静态调整 echo https://你的域名/plus/view.php?aid{$row[arcid]}\n; }这段代码的逻辑很直白连库、筛出近期有效文章、按固定格式输出 URL。参数上arcrank 0过滤未审核内容ismake 1确保是已生成静态的senddate限制时间窗口避免一次吐出几十万条把蜘蛛吓跑。LIMIT 500是单次输出上限配合分页参数可以做成多页入口。跑通之后把这份清单提交给搜索引擎的抓取入口观察日志里这些 URL 的响应码和抓取间隔。如果响应码稳定在 200、抓取间隔在缩短说明入口策略有效可以进入下一步做频次控制和日志记录。3. 用插件把抓取频次和日志做成可观测闭环3.1 频次控制别让蜘蛛一次吃撑蜘蛛抓取频次不是越高越好。同一时间并发太高服务器扛不住返回 503蜘蛛会判定站点不稳定反而降低整体抓取量。dede蜘蛛爬行插件里通常有一个频次令牌桶按 IP 或 User-Agent 识别蜘蛛给每个蜘蛛分配一个每秒/每分钟的请求配额超出的请求直接返回 429 或 503 并带Retry-After头。下面是一个简化的令牌桶实现挂在common.inc.php里对蜘蛛请求生效。?php // spider_rate_limit.php 蜘蛛频次限制 function spider_rate_limit($ip, $ua, $limit 10, $window 60) { // 只对已知蜘蛛 UA 生效普通用户不限制 $spider_keys [Baiduspider, Googlebot, bingbot, Sogou web spider]; $is_spider false; foreach ($spider_keys as $key) { if (stripos($ua, $key) ! false) { $is_spider true; break; } } if (!$is_spider) return true; $dir /tmp/spider_rl/; if (!is_dir($dir)) mkdir($dir, 0755, true); $file $dir . md5($ip . $ua) . .json; $now time(); $data [start $now, count 0]; if (file_exists($file)) { $data json_decode(file_get_contents($file), true); // 窗口过期则重置 if ($now - $data[start] $window) { $data [start $now, count 0]; } } $data[count]; file_put_contents($file, json_encode($data)); if ($data[count] $limit) { header(HTTP/1.1 429 Too Many Requests); header(Retry-After: . ($window - ($now - $data[start]))); exit; } return true; }参数说明$limit 10表示每个蜘蛛每 60 秒最多 10 次请求这个值要根据你服务器实际承载能力调。小站建议从 5 开始观察 CPU 和响应时间再往上加。$window是统计窗口单位秒。文件存储用/tmp是为了快但重启会丢生产环境可以换成 Redis 或数据库。注意Retry-After头一定要带它告诉蜘蛛“过多久再来”比直接 503 不带信息友好得多。这个闭环跑起来后你会在日志里看到蜘蛛请求被平滑地摊开而不是一阵一阵地冲击。3.2 爬行日志把蜘蛛行为记成可查询的表没有日志的频次控制是黑匣子。你只知道限制了不知道限制了多少、哪些页面被反复抓、哪些页面蜘蛛根本不碰。dede蜘蛛爬行插件一般会建一张独立日志表记录每次蜘蛛请求的 URL、UA、IP、响应码、耗时。建表 SQL 如下CREATE TABLE IF NOT EXISTS dede_spider_log ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, url varchar(500) NOT NULL DEFAULT , spider varchar(100) NOT NULL DEFAULT , ip varchar(45) NOT NULL DEFAULT , status smallint(5) unsigned NOT NULL DEFAULT 0, cost_ms int(10) unsigned NOT NULL DEFAULT 0, created_at int(10) unsigned NOT NULL DEFAULT 0, PRIMARY KEY (id), KEY idx_spider_time (spider, created_at), KEY idx_url (url(191)) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;写入时机放在请求结束前用register_shutdown_function保证即使脚本中途退出也能记录。字段设计上url留 500 长度是因为织梦有些带参数的 URL 很长spider存识别出的蜘蛛名status存 HTTP 响应码cost_ms存耗时用来发现慢页面。索引建在spider created_at上方便按蜘蛛和时间段查url前缀索引用于查某个页面被抓了多少次。有了这张表你可以直接跑 SQL 回答“百度蜘蛛最近 7 天抓了哪些页面”“哪些页面返回 404 还在被反复抓”这类问题优化方向就从猜变成了看数据。3.3 把日志用起来三个必查的排查查询日志表建好只是第一步关键是用它做决策。下面三条 SQL 是我在排查抓取问题时最常跑的。第一条查高频 404这些 URL 要么做 301 要么从入口里去掉SELECT url, COUNT(*) AS hits FROM dede_spider_log WHERE status 404 AND created_at UNIX_TIMESTAMP() - 86400 * 7 GROUP BY url ORDER BY hits DESC LIMIT 20;第二条查抓取量趋势按天看蜘蛛活跃度判断频次调整是否生效SELECT FROM_UNIXTIME(created_at, %Y-%m-%d) AS day, spider, COUNT(*) AS reqs FROM dede_spider_log WHERE created_at UNIX_TIMESTAMP() - 86400 * 30 GROUP BY day, spider ORDER BY day DESC;第三条查慢页面cost_ms超过 2000 的页面蜘蛛容易超时放弃需要单独优化SELECT url, AVG(cost_ms) AS avg_cost, COUNT(*) AS hits FROM dede_spider_log WHERE cost_ms 2000 AND created_at UNIX_TIMESTAMP() - 86400 * 7 GROUP BY url ORDER BY avg_cost DESC LIMIT 20;这三条查询覆盖了抓取问题的大部分场景入口脏、频次异常、页面慢。跑一段时间后你会对自家站点的蜘蛛行为形成肌肉记忆再调参数就有据可依。4. 避坑dede蜘蛛爬行插件落地时最容易翻车的五件事4.1 现象蜘蛛抓取量突然归零日志里全是 503原因通常是频次限制设得太狠或者令牌桶文件目录权限不对导致每次请求都新建文件、磁盘 IO 打满。解决先把$limit临时调到 100 观察确认是限制问题后逐步下调同时检查/tmp/spider_rl/目录是否可写建议换成 Redis 存储避免文件锁竞争。另外注意如果你在 Nginx 层也配了限流两层叠加会把蜘蛛彻底挡在外面排查时要先把 Nginx 限流关掉做对照。4.2 现象入口列表里混进了搜索页和标签页蜘蛛抓了一堆重复内容原因是生成入口时直接SELECT了所有 URL没有过滤plus/search.php、tags.php这类动态页。解决在 SQL 里加AND typeid NOT IN (排除的栏目ID)或者在输出前用正则过滤掉含search、tags、?参数的 URL。更彻底的做法是在robots.txt里屏蔽这些路径但注意 robots 只是建议入口列表的过滤才是硬约束。4.3 现象日志表涨到几千万行查询越来越慢原因是没做清理策略蜘蛛日志是只增不减的。解决加一个定时任务每天删除 30 天前的记录或者按月分表。如果不想动表结构至少给created_at单独建索引删除时用WHERE created_at ?走索引批量删避免全表扫描。我一般会在插件里带一个clean_log.php用 crontab 每天凌晨跑一次删除时每批 1000 行防止长事务锁表。4.4 现象改了频次参数后不生效蜘蛛还是按老节奏抓原因是织梦有页面缓存common.inc.php里的逻辑被缓存文件跳过了。解决清空data/cache/和data/tplcache/目录或者在插件入口处加define(DEDE_DEBUG, true)强制不走缓存。另外确认你的挂载点是在缓存逻辑之前还是之后如果织梦先输出缓存再执行你的代码那频次控制永远不会触发。这个坑很隐蔽建议在插件里加一行error_log确认每次请求都走到了。4.5 现象蜘蛛来了但只抓首页内页一个不碰原因通常是内页链接是 JS 动态生成的或者用了nofollow但没留可抓入口。解决检查模板里内容页链接是否直接输出在 HTML 里如果是 JS 渲染蜘蛛拿不到。可以在入口列表里直接输出内页 URL 作为补充相当于给蜘蛛开了一条“直达通道”。另外确认robots.txt没有误屏蔽内页路径这个低级错误我见过不止一次排查时先看 robots 再看代码。5. 进阶把爬行数据反哺到内容更新策略跑通基础版之后这套插件真正的价值在于反哺内容策略。我一般会加一个“抓取热度”字段按 URL 统计最近 7 天被抓次数然后和内容更新表做关联。抓取次数高但内容老旧的页面优先安排更新抓取次数低但内容重要的页面手动加内链或者放进入口列表前排。具体做法是在日志表基础上建一个汇总表每天凌晨跑一次聚合INSERT INTO dede_spider_hot (url, hits_7d, last_crawl) SELECT url, COUNT(*) AS hits_7d, MAX(created_at) FROM dede_spider_log WHERE created_at UNIX_TIMESTAMP() - 86400 * 7 GROUP BY url ON DUPLICATE KEY UPDATE hits_7d VALUES(hits_7d), last_crawl VALUES(last_crawl);这张汇总表可以和织梦的archives表按aid关联输出一份“高抓取低更新”的清单。我通常每周看一次这份清单把排名前 50 的页面挑出来要么补充内容要么调整内链结构。另一个技巧是把抓取频次和服务器负载做联动如果cost_ms均值超过 1500ms自动把$limit下调 20%等负载恢复再调回来。这个自适应逻辑用 crontab 每 10 分钟跑一次判断即可不需要多复杂。参数上hits_7d的阈值我一般设在 10 次以上算“高抓取”低于 3 次算“低抓取”。这两个值不是固定的内容量大的站可以按分位数来定比如取前 20% 作为高抓取。最后提醒一句所有频次和入口策略都要以日志数据为准别凭感觉调。我早期吃过亏觉得蜘蛛来得少就拼命放开限制结果服务器被打挂蜘蛛直接降权恢复花了两个月。现在我的习惯是每次调参前先跑一遍那三条排查 SQL确认基线再动手。希望帮到你。本文还有配套的精品资源点击获取