用美丽的汤解析谷歌内部卡片

Posted

技术标签:

【中文标题】用美丽的汤解析谷歌内部卡片【英文标题】:Parse Google inner cards with Beautiful soup 【发布时间】:2018-07-23 14:37:57 【问题描述】:

我正在尝试解析g-inner-card class = "_KBh",但由于某种原因,它返回了一个空元组。 linkElems = soup.select('._KBh a')

linkElems = soup.select('._KBh a')

print(linkElems)

这会返回一个空元组[]

import webbrowser, sys, pyperclip, requests, bs4
if len(sys.argv) > 1:
    term = ' '.join(sys.argv[1:])
else:
    term = pyperclip.paste()
res = requests.get("https://www.google.com/search?q="+term)
try:
    res.raise_for_status()
except Exception as ex:
    print('There was a problem: %s' %(ex), '\nSorry!!')
soup = bs4.BeautifulSoup(res.text, "html.parser")
linkElems = soup.select('._KBh a')
print(linkElems)
numOpen = min(3, len(linkElems))
for i in range(numOpen):
    print(linkElems[i].get('href'))
    webbrowser.open('https://google.com/' + linkElems[i].get('href'))

这段代码sn-p试图在浏览器的3个不同窗口中打开最多3个google搜索结果,当输入命令行参数(即要搜索的词)时,它专门显示google内卡的结果。

【问题讨论】:

它应该找到什么意思?有什么地方可以找到这门课吗? 编辑了问题以便更好地理解。希望它能澄清你的疑惑。如果还不清楚,请再问。 res.text 中有什么内容?因为没有适当的数据就无法继续执行您的代码 sn-p,对吧? 不,它没有。我在任何地方都找不到课程,你确定它存在吗? 再次编辑。很抱歉数据不完整。第一次问问题。希望对您有所帮助。 【参考方案1】:

如果您打印res.text,您可以看到您没有从页面获取完整/正确的数据。发生这种情况是因为 Google 阻止了 Python 脚本。

要克服这个问题,您可以传递一个User-Agent 以使脚本看起来像一个真正的浏览器。

默认User-Agent的结果:

>>> URL = 'https://www.google.co.in/search?q=federer'
>>> res = requests.get(URL)
>>> '_KBh' in res.text
False

添加自定义User-Agent后:

>>> headers = 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
>>> res = requests.get(URL, headers=headers)
>>> '_KBh' in res.text
True

headers 添加到您的代码中,会得到以下输出(您要查找的前 3 个链接):

https://www.express.co.uk/sport/tennis/918251/Roger-Federer-Felix-Auger-Aliassime-practice
https://sports.yahoo.com/breaks-lighter-schedules-help-players-improve-says-federer-092343458--ten.html
http://www.news18.com/news/sports/rafael-nadal-stays-atop-atp-rankings-roger-federer-aims-to-overtake-1658665.html

【讨论】:

抱歉,迟到了。这工作正常,但相同的标题对我的浏览器不起作用(窗口打开但显示错误“未在服务器上找到”即 404)。所以我研究了如何制作自定义标题,但没有成功。请澄清如何制作或提供链接:) 另外,你怎么能得出结论,添加自定义标题将提供解决方案(即谷歌阻止了 py 脚本)。谢谢。 您得到了一个404,因为当网址完成时,您将网址附加到'https://google.com/'(即https://www.express.co.uk/...)。使用webbrowser.open(linkElems[i].get('href'))。它会起作用的。 标题没有问题,只有webbrowser.open(...)部分。至于你的第二个问题,我帖子的第一句话就是答案。随着网络抓取的推进,您会在不同的网站上多次遇到此类问题(被阻止的 python 脚本)。同样的事情发生在我身上很多次,这就是为什么我可以得出结论,添加自定义标题可以提供解决方案。 也在想同样的事情。但是您如何提供自定义标头的规范。请说明:) 我没有自己创建那个用户代理。它是浏览器的用户代理 (you can find it here)。看看this question。我想它会回答你的问题。【参考方案2】:

正如提到的另一个答案,这是因为没有指定user-agent。默认的requestsuser-agent 是python-requests,因此Google 会阻止请求,因为它知道这是一个机器人而不是“真正的”用户访问。 Check what's your user-agent.

如果你想刮很多,另一个好主意是rotate user-agent 或添加header ordering 以降低对被阻止请求的更改。


代码和example in the online IDE:

from bs4 import BeautifulSoup
import requests, 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": "samurai cop what does katana mean",
  "gl": "in",
  "hl": "en"


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

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

-------
'''
Samurai Cop - He speaks fluent Japanese - YouTube
https://www.youtube.com/watch?v=paTW3wOyIYw

Samurai Cop - What does "katana" mean? - Quotes.net
https://www.quotes.net/mquote/1060647

Samurai Cop (1991) - Mathew Karedas as Joe Marshall - IMDb
https://www.imdb.com/title/tt0130236/characters/nm0360481

...
'''

或者,您可以使用来自 SerpApi 的 Google Organic Results API 来实现相同的目的。这是一个带有免费计划的付费 API。

您的情况的不同之处在于,无需弄清楚为什么某些事情不能按应有的方式工作,然后随着时间的推移维护解析器,唯一需要做的就是迭代结构化 JSON并快速获取您想要的数据。

要集成的代码:

import os
from serpapi import GoogleSearch

params = 
    "engine": "google",
    "q": "samurai cop what does katana mean",
    "hl": "en",
    "gl": "in",
    "api_key": os.getenv("API_KEY"),


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

for result in results["organic_results"]:
  print(result['title'])
  print(result['link'])
  print()

------
'''
Samurai Cop - He speaks fluent Japanese - YouTube
https://www.youtube.com/watch?v=paTW3wOyIYw

Samurai Cop - What does "katana" mean? - Quotes.net
https://www.quotes.net/mquote/1060647
...
'''

免责声明,我为 SerpApi 工作。

【讨论】:

以上是关于用美丽的汤解析谷歌内部卡片的主要内容,如果未能解决你的问题,请参考以下文章

美丽的汤解析网页

美丽的汤和桌子刮 - lxml 与 html 解析器

BeautifulSoup,一碗美丽的汤,一个隐藏的大坑

美丽的汤在源文件中找到标记的位置?

用美丽的汤刮痧数据

如何用漂亮的汤刮掉谷歌搜索的第一个链接