用Beautiful Soup解析HTML

0 投票
1 回答
615 浏览
提问于 2025-04-17 21:33

我有一个元组,里面定义了我感兴趣的链接关键词,具体如下:

categories = ('car', 'planes', ...)

我想把某个特定类里面的所有链接放到一个列表里,这些链接的内容要和我元组里的任意一个值匹配。文档内容如下:

<div class='content'>
    <ul class='side-panel'>
        <li><a href='page1.html'>page 1</a></li>
        <li><a href='page2.html'>page 2</a></li>
        <li><a href='best_car_2013.html'>Best Cars</a></li>
        ...
    </ul>
</div>

目前我在做的是:

found = []

for link in soup.find_all(class_='side-panel'):
    for category in categories:
        if re.search(category, link.get('href')):
            found.append(link)

但是我遇到了一个类型错误,提示“期望是字符串或缓冲区”。在调试脚本时,我发现我获取到了所有的 'li' 标签以及它们对应的锚点标签,但我在遍历这些结果时遇到了麻烦,无法从中提取出每个链接的 'href' 属性,并把它们放到列表里。

1 个回答

2

每当你需要手动遍历标签来进行额外的筛选时,其实直接使用 bs4 的接口会更好。在这种情况下,你可以把正则表达式传给 find_all 方法。

soup.find(class_='side-panel').find_all(href=re.compile('|'.join(categories)))
Out[86]: [<a href="best_car_2013.html">Best Cars</a>]

如果不太明白,把 categories 用管道符连接成一个表达式,可以让 re 引擎判断是否有 任何 类别与 href 属性匹配。这样就不需要逐个遍历每个类别并单独进行 re 搜索了。

编辑:(提到评论中的链接)看起来你抓取的页面有 两个 class='side-panel categories' 标签(???),所以在最初的 find_all 操作后再进行更多的 find_all 操作可能是合适的:

[t for tags in soup.find_all(class_='side-panel categories') 
    for t in tags.find_all(href=re.compile('|'.join(selected_links)))]
Out[24]: 
[<a href="/animals__birds-desktop-wallpapers.html">Animals &amp; Birds</a>,
 <a href="/beach-desktop-wallpapers.html">Beach</a>,
 <a href="/bikes__motorcycles-desktop-wallpapers.html">Bikes</a>,
 <a href="/cars-desktop-wallpapers.html">Cars</a>,
 <a href="/digital_universe-desktop-wallpapers.html">Digital Universe</a>,
 <a href="/flowers-desktop-wallpapers.html">Flowers</a>,
 <a href="/nature__landscape-desktop-wallpapers.html">Nature</a>,
 <a href="/planes-desktop-wallpapers.html">Planes</a>,
 <a href="/travel__world-desktop-wallpapers.html">Travel &amp; World</a>,
 <a href="/vector__designs-desktop-wallpapers.html">Vector &amp; Designs</a>]

撰写回答