如何在 Python 中使用 BeautifulSoup 解析谷歌搜索结果

Posted

技术标签:

【中文标题】如何在 Python 中使用 BeautifulSoup 解析谷歌搜索结果【英文标题】:How to use BeautifulSoup to parse google search results in Python 【发布时间】:2018-06-04 08:18:29 【问题描述】:

我正在尝试解析谷歌搜索结果的第一页。具体来说,提供的标题和小摘要。这是我目前所拥有的:

from urllib.request import urlretrieve
import urllib.parse
from urllib.parse import urlencode, urlparse, parse_qs
import webbrowser
from bs4 import BeautifulSoup
import requests

address = 'https://google.com/#q='
# Default Google search address start
file = open( "OCR.txt", "rt" )
# Open text document that contains the question
word = file.read()
file.close()

myList = [item for item in word.split('\n')]
newString = ' '.join(myList)
# The question is on multiple lines so this joins them together with proper spacing

print(newString)

qstr = urllib.parse.quote_plus(newString)
# Encode the string

newWord = address + qstr
# Combine the base and the encoded query

print(newWord)

source = requests.get(newWord)

soup = BeautifulSoup(source.text, 'lxml')

我现在坚持的部分是沿着 html 路径解析我想要的特定数据。到目前为止我尝试过的所有东西都只是抛出一个错误,说它没有属性或者它只是返回“[]”。

我是 Python 和 BeautifulSoup 的新手,所以我不确定如何到达我想要的地方的语法。我发现这些是页面中的单个搜索结果:

https://ibb.co/jfRakR

任何关于添加什么来解析每个搜索结果的标题和摘要的帮助将不胜感激。

谢谢!

【问题讨论】:

您可能会为此苦苦挣扎,因为 Google 使用 javascript 呈现其大量页面,因此您看到的标记如果不存在于下载的数据中。您是否检查了您想要的标记存在的实际数据?您可能需要考虑使用 Google 自定义搜索 API developers.google.com/custom-search/json-api/v1/overview,因为我听说 Google 会定期更改其搜索结果页面上的标记。 Google 使用 JavaScript 将数据放在页面上。 BS 不运行 JavaScript。如果您在浏览器中关闭 JavaScript 并加载 Google 页面,那么您会看到它发送的页面包含数据,但标签不同。 【参考方案1】:

您的网址不适合我。但是使用https://google.com/search?q= 我会得到结果。

import urllib
from bs4 import BeautifulSoup
import requests
import webbrowser

text = 'hello world'
text = urllib.parse.quote_plus(text)

url = 'https://google.com/search?q=' + text

response = requests.get(url)

#with open('output.html', 'wb') as f:
#    f.write(response.content)
#webbrowser.open('output.html')

soup = BeautifulSoup(response.text, 'lxml')
for g in soup.find_all(class_='g'):
    print(g.text)
    print('-----')

阅读Beautiful Soup Documentation

【讨论】:

【参考方案2】:
    默认 Google 搜索地址开始不包含 # 符号。相反,它应该有?/search pathname:
---> https://google.com/#q=
---> https://www.google.com/search?q=cake
    确保将user-agent 传递到HTTP request headers 以使其工作,因为默认的python user-agentpython-requests,并且站点可以识别它并阻止脚本。检查Robots.txt 了解更多信息。 这可能是您得到空结果的原因。 Check what's your user-agent。 List of user-agents

Pass user-agent in request headers:

headers = 
    'User-agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582'

requests.get('YOUR_URL', headers=headers)

代码和example in the online IDE:

from bs4 import BeautifulSoup
import requests, json, lxml

headers = 
    'User-agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582'


params = 
  'q': 'tesla',  # query 
  'gl': 'us',    # country to search from
  'hl': 'en',    # language


html = requests.get("https://www.google.com/search", headers=headers, params=params)
soup = BeautifulSoup(html.text, 'lxml')

data = []

for result in soup.select('.tF2Cxc'):
  title = result.select_one('.DKV0Md').text
  link = result.select_one('.yuRUbf a')['href']

  # sometimes there's no description and we need to handle this exception
  try: 
    snippet = result.select_one('#rso .lyLwlc').text
  except: snippet = None

data.append(
   'title': title,
   'link': link,
   'snippet': snippet,
)

print(json.dumps(data, indent=2, ensure_ascii=False))

-------------
'''
[
  
    "title": "Tesla: Electric Cars, Solar & Clean Energy",
    "link": "https://www.tesla.com/",
    "snippet": "Tesla is accelerating the world's transition to sustainable energy with electric cars, solar and integrated renewable energy solutions for homes and ..."
  ,
  
    "title": "Tesla, Inc. - Wikipedia",
    "link": "https://en.wikipedia.org/wiki/Tesla,_Inc.",
    "snippet": "Tesla, Inc. is an American electric vehicle and clean energy company based in Palo Alto, California, United States. Tesla designs and manufactures electric ..."
  ,
  
    "title": "Nikola Tesla - Wikipedia",
    "link": "https://en.wikipedia.org/wiki/Nikola_Tesla",
    "snippet": "Nikola Tesla was a Serbian-American inventor, electrical engineer, mechanical engineer, and futurist best known for his contributions to the design of the ..."
  
]
'''

或者,您可以使用来自 SerpApi 的 Google Organic Results API 来实现相同的目的。这是一个付费 API,提供免费计划,仅用于测试 API。

您的情况的不同之处在于,您不必弄清楚为什么输出为空以及导致这种情况发生的原因,绕过来自 Google 或其他搜索引擎的块,然后随着时间的推移维护解析器。相反,您只需要从您想要的结构化 JSON 中快速获取数据。

要集成的代码:

import os
from serpapi import GoogleSearch

params = 
  "engine": "google",
  "q": "tesla",
  "hl": "en",
  "gl": "us",
  "api_key": os.getenv("API_KEY"),


search = GoogleSearch(params)
results = search.get_dict()

for result in results["organic_results"]:

  print(f"Title: result['title']\nSummary: result['snippet']\nLink: result['link']\n")

----------
'''
Title: Tesla: Electric Cars, Solar & Clean Energy
Summary: Tesla is accelerating the world's transition to sustainable energy with electric cars, solar and integrated renewable energy solutions for homes and ...
Link: https://www.tesla.com/

Title: Tesla, Inc. - Wikipedia
Summary: Tesla, Inc. is an American electric vehicle and clean energy company based in Palo Alto, California, United States. Tesla designs and manufactures electric ...
Link: https://en.wikipedia.org/wiki/Tesla,_Inc.
'''

免责声明,我为 SerpApi 工作。

【讨论】:

在免费计划下,serpAPI 每月是否只允许 100 次搜索? serpapi.com/pricing @gnoodle 如果您想要超过 100 个请求,contact SerpApi directly。在您看来,什么才是好的免费计划? 我并不是在批评 SerpAPI 只提供 100 个请求。我只是将其指出为与大多数阅读您的答案的人相关的事实。我看到您在回答许多类似问题时发布了与此类似的答案,我建议您在所有答案中澄清这一限制。 但在回答您的问题时,如果打算允许免费演示您的 API,我想 100-200 就足够了,这样人们就可以理解了。但是做任何有意义的事情通常需要至少 1000 个请求 @gnoodle 感谢您的反馈并感谢您的想法。

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

Python - 分配打印输出csv

python beautifulsoup获取特定html源码

用python的BeautifulSoup分析html

如何用 Beautifulsoup 解析“数据文本”? [复制]

运行 pub get 时出错:无法重命名目录,因为它正在被另一个进程使用

Linux中安装pip和BeautifulSoup(bs4)