如何使用 bs4 正确解析谷歌搜索结果?

Posted

技术标签:

【中文标题】如何使用 bs4 正确解析谷歌搜索结果?【英文标题】:How to correctly parse google search results with bs4? 【发布时间】:2021-08-23 23:10:30 【问题描述】:

我的目标是用 python 编写一个网页抓取程序,它使用 beautifulsoup 解析谷歌搜索结果页面,并一次打开多个结果链接。程序如下所示:

#! python3
# searchGoogle.py - Opens several google results.

import requests, sys, webbrowser, bs4
print('Searching...') # display text while downloading the result page
res = requests.get('https://www.google.com/search?q=' + ' '.join(sys.argv[1:]))
res.raise_for_status()

# Retrieve top search result links.
soup = bs4.BeautifulSoup(res.text, 'html.parser')

# Open a browser tab for each result.
linkElems = soup.select('div.yuRUbf > a')
numOpen = min(5, len(linkElems))
for i in range(numOpen):
    urlToOpen = linkElems[i].get('href')
    print('Opening', urlToOpen)
    webbrowser.open(urlToOpen)

由于我的 HTML 技能有限,我不太清楚如何检索包含链接的 HTML 元素。

这是我要解析的网页: https://www.google.com/search?q=boring+stuff

我的浏览器的开发者控制台显示以下 HTML 代码:

所有链接都在带有 class="yuRUbf" 的元素中(我在附图中标记了一个示例。)

我的问题: 我必须传递给 soup.select() 方法的正确论点是什么?因为所有 'a' 元素都直接在 'div' 元素中,并且这些元素具有名为 'yuRUbf' 的类属性,所以我认为 'div.yuRUbf > a' 是正确的......但程序不起作用。网页没有在浏览器中打开。

哪位经验丰富的 HTML 开发人员可以帮助我解决这个问题?我传递给soup.select() 方法的论点不正确吗?应该是什么?还是其他地方有问题?

我正在使用 MacOS Catalina 和 Python 3.8。

【问题讨论】:

请粘贴指向该网页的链接,或者粘贴实际代码,而不是图像。如果有人想尝试您的代码以提供帮助,我们需要实际的 html 来对其进行测试。 DOM ≠ 页面源。由于看起来您使用的是 chrome,因此您将使用像 requests 这样的 HTTP 客户端获得的页面的更准确表示将在实际的 View Page Source 视图中(Windows:CTRL- U,macOS:Command-U)。您所定位的元素可能都不存在于实际页面源中,而是使用 javascript 动态生成的,requestsBeautifulSoup 都无法解释/执行。 @William 好的,抱歉,我将链接发布到搜索结果页面。 @aurumpurum 你想学习 bs4 吗?还是解析谷歌?如果你想搜索谷歌,有一个很棒的包:pypi.org/project/googlesearch-python @William 尝试学习 bs4 以进行网络抓取 :-) 我知道还有其他软件包,例如 selenium,但我想一步一步地进行。感谢您的 googlesearch_python 软件包!看起来很有趣,会去看看!干杯。 【参考方案1】:

再次阅读问题,如果你想打开google搜索链接,你应该使用现有的工具: Searching in Google with Python

特别是很棒的谷歌搜索包:https://pypi.org/project/googlesearch-python/

最好不要重新发明***,除非现有的包不能做你想做的事情(或者如果你正在尝试学习 bs4)。

编辑:重新阅读问题,您专门询问了beautifulsoup。我的错。

【讨论】:

【参考方案2】:

要从 Google 服务器获得正确的结果,请设置 User-Agent HTTP 标头。然后您可以使用 CSS 选择器 a:has(h3) 来获取您的链接:

import requests
from bs4 import BeautifulSoup


url = "https://www.google.com/search"
params = "q": "boring stuff"  # add "hl":"en" to get english results
headers = 
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0"

soup = BeautifulSoup(
    requests.get(url, params=params, headers=headers).content, "html.parser"
)

for a in soup.select("a:has(h3)"):
    print(a["href"])

打印:

https://automatetheboringstuff.com/
https://www.martinus.sk/?uItem=231151
https://www.amazon.com/Automate-Boring-Stuff-Python-2nd/dp/1593279922
https://www.amazon.com/Automate-Boring-Stuff-Python-Programming/dp/1593275994
https://knihy.heureka.sk/automate-the-boring-stuff-with-python-sweigart-albert/
https://www.udemy.com/course/automate/
https://inventwithpython.com/blog/2019/10/07/whats-new-in-the-2nd-edition-of-automate-the-boring-stuff-with-python/
https://towardsdatascience.com/how-to-use-bash-to-automate-the-boring-stuff-for-data-science-d447cd23fffe
https://www.barnesandnoble.com/w/automate-the-boring-stuff-with-python-2nd-edition-al-sweigart/1133598925

【讨论】:

谢谢!看起来不错,我会深入检查...因为我正在学习如何使用 CSS 选择器:你能评论我尝试将 'div.yuRUbf > a' 传递给 soup.select() 方法吗?我的想法完全错误吗?或者我可以适应它吗?只是出于好奇,在我继续检查您的解决方案之前。谢谢! @aurumpurum 根据经验,当我看到诸如"yuRUbf" 之类的类名时,我知道它们经常(通常)更改。所以我试图找到其他的“模式”。就像在这个网站上一样:我看到链接文本在 <h3> 标签内,所以我使用这些信息来构建 CSS 选择器。 好的,有道理,谢谢。但是你在哪里看到

标签?在我的开发者控制台中,我没有看到任何东西(见打印屏幕)。同样,这只是为了从这个案例中吸取教训......

@aurumpurum 我通常使用print(soup.prettify()) 来观察服务器返回的 HTML。 嗨,Andrej,我还在处理这个案例:soup.select("a:has(h3)") 给我一个空列表。有什么问题?有什么办法可以给你看我的代码吗?我想了解更多关于为什么我必须传递 headers 参数并更改 User-Agent...

以上是关于如何使用 bs4 正确解析谷歌搜索结果?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 bs4 打印第一个 google 搜索结果链接?

如何解析谷歌地图地理编码结果

《爬虫学习》(使用lxml,bs4库以及正则表达式解析数据)

从谷歌搜索中提取结果数量

我想知道谷歌搜索引擎如何立即挑选结果

如何正确使用手册页