如何使用 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 动态生成的,requests
和 BeautifulSoup
都无法解释/执行。
@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 正确解析谷歌搜索结果?的主要内容,如果未能解决你的问题,请参考以下文章