如何在现有Node.js爬虫实现中添加下一页帖子链接抓取逻辑
实现思路
- 补全原代码缺失的基础域名变量
base_link,避免链接拼接时报错 - 为抓取方法增加当前页面URL参数,支持传入不同分页地址发起请求
- 每次完成当前页帖子链接提取后,同步提取分页区下一页按钮对应的访问地址
- 采用递归调用逻辑,只要存在下一页地址就继续爬取,直到无下一页时返回所有收集到的链接
- 新增请求延时和错误捕获逻辑,避免请求频率过高被站点封禁,同时方便问题排查
完整可运行代码
const request = require('request'); const cheerio = require('cheerio'); // 补全基础域名 const base_link = 'https://stackoverflow.com'; // 初始爬取的入口页地址 const startLink = 'https://stackoverflow.com/questions/tagged/web-scraping'; // 存储所有抓取到的帖子链接 const items = []; // 新增currentUrl参数,接收要爬取的页面地址 let getLinks = (currentUrl) => { return new Promise((resolve, reject) => { // 1秒请求延时,不需要可直接删除setTimeout包裹层 setTimeout(() => { request(currentUrl, function(error, response, html) { let $ = cheerio.load(html); if (error) return reject(error); try { // 提取当前页所有帖子链接存入数组 $('.summary > h3 > a.question-hyperlink').each(function() { items.push(base_link + $(this).attr("href")); }); // 提取下一页的相对地址 const nextPageHref = $('.s-pagination--item__next a').attr('href'); if (nextPageHref) { // 存在下一页,拼接为完整地址后递归爬取 const nextPageUrl = base_link + nextPageHref; resolve(getLinks(nextPageUrl)); } else { // 无下一页,返回所有收集到的链接 resolve(items); } } catch (e) { reject(e); } }); }, 1000) }); }; // 传入初始地址启动爬取 getLinks(startLink).then(resultList => { resultList.forEach(link => console.log(link)); console.log(`爬取完成,共获取到${resultList.length}条帖子链接`); }).catch(err => { console.error('爬取过程出错:', err); })
核心逻辑说明
- 下一页地址通过Stack Overflow站点分页区的下一页按钮选择器
.s-pagination--item__next a提取,该选择器适配当前站点的页面结构,如果后续站点页面迭代调整,只需要同步修改对应的选择器即可 - 递归调用会自动等待前一页请求完成后再发起下一页请求,不会出现并发请求过高的问题
- 如果需要限定爬取的最大页数,可以额外增加一个计数器变量,每爬完一页计数器加1,达到设定阈值时直接返回结果即可
内容的提问来源于stack exchange,提问作者MITHU
相关产品推荐
相关产品推荐

