【问题标题】:How to correctly parse google search results with bs4?如何使用 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 软件包!看起来很有趣,会去看看!干杯。

标签: python html parsing web-scraping


【解决方案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...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    • 2021-06-03
    • 2018-06-04
    • 2011-05-03
    相关资源
    最近更新 更多