使用 BeautifulSoup 进行导航

Posted

技术标签:

【中文标题】使用 BeautifulSoup 进行导航【英文标题】:Navigation with BeautifulSoup 【发布时间】:2016-01-28 23:50:58 【问题描述】:

我对如何使用 BeautifulSoup 导航 html 树感到有些困惑。

import requests
from bs4 import BeautifulSoup

url = 'http://examplewebsite.com'
source = requests.get(url)
content = source.content
soup = BeautifulSoup(source.content, "html.parser")

# Now I navigate the soup
for a in soup.findAll('a'):
    print a.get("href")

    有没有办法通过标签仅找到特定 href?例如,我想要的所有href 都以某个名称命名,例如price 在在线目录中。

    我想要的href链接都在网页内的某个位置,在页面内和某个 .我可以只访问这些链接吗?

    如何抓取每个href 链接中的内容并保存为文件格式?

【问题讨论】:

(2) “特定位置”是什么意思。你能给出源文件的摘录吗?它是“靠近

”标签还是什么? (3) 链接的“内容”是什么意思?您要下载链接另一端的文件吗?

@RobertB (2) 是的,我的意思是在某个<table> 中有多个href (3) 你点击一个链接,直到你到达一个数据表。我想抓取这些数据。 【参考方案1】:

有了BeautifulSoup,这一切都是可行且简单的。

(1) 有没有办法通过标签只找到特定的href?为了 例如,我想要的所有 href 都以某个名称调用,例如 在线目录中的价格。

比如说,你需要的所有链接在文本中都有price - 你可以使用text 参数:

soup.find_all("a", text="price")  # text equals to 'price' exactly
soup.find_all("a", text=lambda text: text and "price" in text)  # 'price' is inside the text

是的,您可以使用functions 和许多其他不同类型的对象来过滤元素,例如,编译后的regular expressions:

import re

soup.find_all("a", text=re.compile(r"^[pP]rice"))

如果price 位于“href”属性中,您可以使用以下CSS selector:

soup.select("a[href*=price]")  # href contains 'price'
soup.select("a[href^=price]")  # href starts with 'price'
soup.select("a[href$=price]")  # href ends with 'price'

或者,通过find_all()

soup.find_all("a", href=lambda href: href and "price" in href)

(2) 我想要的href链接都在 网页,在页面内和某个 .我可以只访问这些吗 链接?

好的,找到合适的容器并致电find_all() or other searching methods:

container = soup.find("div", class_="container")
for link in container.select("a[href*=price"):
    print(link["href"])

或者,您可以编写 CSS 选择器,就像在具有所需属性或属性值的特定元素内搜索链接一样。例如,这里我们正在搜索具有href 属性的a 元素位于具有container 类的div 元素内:

soup.select("div.container a[href]")

(3) 如何抓取每个 href 链接中的内容并保存到 文件格式?

如果我理解正确,您需要获取适当的链接,关注它们并将页面的源代码本地保存到 HTML 文件中。根据您的要求,有多种选项可供选择(例如,速度可能很关键。或者,它只是一项一次性任务,您不关心性能)。

如果您继续使用requests,代码将具有阻塞性质 - 您将提取链接,点击它,保存页面源代码,然后继续下一个 - 它的主要缺点是它会很慢(首先取决于有多少链接)。示例代码助您一臂之力:

from urlparse import urljoin

from bs4 import BeautifulSoup
import requests

base_url = 'http://examplewebsite.com'
with requests.Session() as session:  # maintaining a web-scraping session
    soup = BeautifulSoup(session.get(base_url).content, "html.parser")

    for link in soup.select("div.container a[href]"):
        full_link = urljoin(base_url, link["href"])
        title = a.get_text(strip=True)

        with open(title + ".html", "w") as f:
            f.write(session.get(full_link).content)

您可以查看grequestsScrapy 来解决这部分问题。

【讨论】:

@alexce "关注他们并将页面的源代码本地保存到 HTML 文件中。"实际上,我需要将每个单独页面的源代码保存到一个 HMTL 文件中。因此,可以将其视为多个网页上的巨大 HTML 树;我需要一直跟踪链接/子节点,保存这些数据,附加到我的文件中,然后继续。 @ShanZhengYang 那么听起来您需要以“追加”模式打开同一个HTML文件,或者只打开一次进行写入并在跟踪链接和下载页面时保持打开状态。谢谢。

以上是关于使用 BeautifulSoup 进行导航的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中使用 Selenium 导航并使用 BeautifulSoup 进行抓取

使用动态滚动解析网页的所有链接

爬虫利器BeautifulSoup模块使用

爬虫之Beautifulsoup及xpath

93解析库之re,Beautifulsoup

添加富文本编辑器使用xss攻击BeautifulSoup4模块富文本编辑器上传图片修改头像)