采集黑马程序员论坛的帖子使用xpath
打开黑马程序员论坛的采集程序帖子列表页,按F12,黑马找到每个帖子标题所在的员论用标签,右键复制XPath——这事儿我干过不下五十次。坛的帖使但每次复制出来的采集程序路径都长得像 `/html/body/div[3]/div[2]/div[1]/ul/li[4]/a` 这种,换一页就废。黑马问题出在论坛的员论用DOM结构会随板块、置顶帖、坛的帖使广告位变化,采集程序绝对路径根本靠不住。黑马
真正能用的员论用XPath,得从帖子标题的坛的帖使共性特征入手。比如黑马论坛的采集程序帖子标题通常带 `class="title"` 或位于 `h3` 标签内,链接的黑马 `href` 包含 `/thread-` 这类固定片段。我一般会写成:
//a[contains(@href,员论用 '/thread-') and string-length(text()) > 5]/text() 这行XPath的意思是:找所有href里带“/thread-”且文本长度大于5的链接,提取文字。为什么加长度限制?因为论坛底部有“上一页”“下一页”这类短链接,不加过滤会混进来。实测下来,一页20个帖子,能准确抓到18-19个,漏掉的是纯图片帖或标题极短的。
用Python的lxml库跑一下:
from lxml import etree import requests url = 'https://bbs.itheima.com/forum-2-1.html' html = requests.get(url, headers={ 'User-Agent': 'Mozilla/5.0'}).text tree = etree.HTML(html) titles = tree.xpath('//a[contains(@href, "/thread-") and string-length(text()) > 5]/text()') for t in titles: print(t.strip()) 注意requests必须带User-Agent,否则黑马论坛会返回403。这个坑我踩过,当时以为是XPath写错了,查了半小时才发现是请求头问题。
翻页怎么办?论坛的分页链接通常是 `forum-2-2.html`、`forum-2-3.html` 这种规律。直接构造URL循环就行,比用XPath抓“下一页”按钮更稳。因为“下一页”按钮在最后一页会消失,XPath返回空列表,逻辑还得额外判断。
还有个细节:帖子标题里可能带换行符或多余空格。比如“【教程】 Spring Boot 入门”这种,直接输出会很难看。我习惯用 `''.join(t.split())` 压掉所有空白。另外,有些帖子标题被截断,末尾带“...”,这是论坛前端做的省略,XPath抓到的就是带省略号的文本,没法还原完整标题——除非点进详情页,但那样效率太低,采集列表页时我选择接受这个缺陷。
如果你要采集的不只是标题,还有作者、回复数、发布时间,那就得换策略。每个帖子的信息块通常在一个 `tbody` 或 `div` 里,用相对XPath从标题链接往上找父节点,再提取兄弟节点的文本。比如:
//a[contains(@href, "/thread-")]/ancestor::tbody[1]//text() 这样能把整个帖子行的所有文字都抓出来,再按换行和空格切分。但不同板块的表格结构不一样,技术交流区用 `tbody`,招聘区可能用 `div`。我的做法是写两套XPath,先试第一套,返回空就换第二套。别指望一个XPath通吃整个论坛。
最后说个观察:黑马论坛的帖子列表在未登录状态下只显示前10页,再往后就要求登录。所以采集深度有限,想抓全量得先搞定登录态,把Cookie带上。不过对于练手XPath来说,前10页足够跑通流程了。真正麻烦的从来不是XPath语法,而是页面结构变来变去——上周还能用的路径,这周论坛改版就失效了。所以写采集脚本时,把XPath单独抽成配置文件,改起来才不痛苦。