Google 中的结果数量错误 Python
Wrong number of results in Google Scrape with Python
我正在尝试学习网络抓取,但我遇到了一个奇怪的问题...我的任务是搜索 Google 特定日期范围内某个主题的新闻并计算结果数。
我的简单代码是
import requests, bs4
payload = {'as_epq': 'James Clark', 'tbs':'cdr:1,cd_min:1/01/2015,cd_max:1/01/2015','tbm':'nws'}
r = requests.get("https://www.google.com/search", params=payload)
soup = bs4.BeautifulSoup(r.text)
elems = soup.select('#resultStats')
print(elems[0].getText())
我得到的结果是
About 8,600 results
所以显然所有的工作...除了结果是错误的。如果我在 Firefox 中打开 URL(我可以用 r.url 获得完整的 URL)
https://www.google.com/search?tbm=nws&as_epq=James+Clark&tbs=cdr%3A1%2Ccd_min%3A1%2F01%2F2015%2Ccd_max%3A1%2F01%2F2015
我看到结果其实是只有2,如果我手动下载HTML文件,打开页面源搜索 id="resultStats" 我发现结果数确实是2个!
谁能帮我理解为什么在保存的 HTML 文件和 soup 项目中搜索相同的 id 标签会导致两个不同的数值结果?
*************** 更新
问题似乎是 requests.get 没有正确处理自定义日期范围。如果我将相同的 URL 与 selenium 一起使用,我会得到正确的答案
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(url)
content = driver.page_source
soup = bs4.BeautifulSoup(content)
elems = soup.select('#resultStats')
print(elems[0].getText())
答案是
2 results (0.09 seconds)
问题是这个方法好像比较麻烦,因为我需要在Firefox中打开页面...
有几件事导致了这个问题。首先,它需要 2 位数字的日期和月份部分,并且还需要一些流行浏览器的用户代理字符串。以下代码应该有效:
import requests, bs4
headers = {
"User-Agent":
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36"
}
payload = {'as_epq': 'James Clark', 'tbs':'cdr:1,cd_min:01/01/2015,cd_max:01/01/2015', 'tbm':'nws'}
r = requests.get("https://www.google.com/search", params=payload, headers=headers)
soup = bs4.BeautifulSoup(r.content, 'html5lib')
print soup.find(id='resultStats').text
添加到 Vikas 的回答中,Google 也将无法对某些用户代理使用 'custom date range'。也就是说,对于某些用户代理,Google 将只搜索 'recent' 结果而不是您指定的日期范围。
我没有检测到用户代理会打破自定义日期范围的明确模式。似乎包括语言是一个因素。
以下是一些破坏 cdr
的用户代理示例:
Mozilla/5.0 (Windows; U; Windows NT 6.1; fr-FR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27
Mozilla/4.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)
selenium
不需要,你要找的是:
soup.select_one('#result-stats nobr').previous_sibling
# About 10,700,000 results
代码和full 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": 'James Clark', # query
"hl": "en", # lang
"gl": "us", # country to search from
"tbm": "nws", # news filter
}
html = requests.get('https://www.google.com/search', headers=headers, params=params)
soup = BeautifulSoup(html.text, 'lxml')
# if used without "nobr" selector and previous_sibling it will return seconds as well: (0.41 secods)
number_of_results = soup.select_one('#result-stats nobr').previous_sibling
print(number_of_results)
# About 10,700,000 results
或者,您可以使用 SerpApi 中的 Google News Results API 来实现相同的目的。这是付费 API 和免费计划。
你的情况的不同之处在于你不必找到哪些选择器可以完成工作,或者弄清楚为什么其中一些不return你想要的数据他们也应该绕过阻止搜索引擎,并随着时间的推移维护它。
相反,您只需要迭代结构化 JSON 并快速获取您想要的数据。
为您的案例集成的代码:
import os
from serpapi import GoogleSearch
params = {
"engine": "google",
"q": 'James Clark',
"tbm": "nws",
"gl": "us",
"api_key": os.getenv("API_KEY"),
}
search = GoogleSearch(params)
results = search.get_dict()
number_of_results = results['search_information']['total_results']
print(number_of_results)
# 14300000
Disclaimer, I work for SerpApi.
我正在尝试学习网络抓取,但我遇到了一个奇怪的问题...我的任务是搜索 Google 特定日期范围内某个主题的新闻并计算结果数。
我的简单代码是
import requests, bs4
payload = {'as_epq': 'James Clark', 'tbs':'cdr:1,cd_min:1/01/2015,cd_max:1/01/2015','tbm':'nws'}
r = requests.get("https://www.google.com/search", params=payload)
soup = bs4.BeautifulSoup(r.text)
elems = soup.select('#resultStats')
print(elems[0].getText())
我得到的结果是
About 8,600 results
所以显然所有的工作...除了结果是错误的。如果我在 Firefox 中打开 URL(我可以用 r.url 获得完整的 URL)
https://www.google.com/search?tbm=nws&as_epq=James+Clark&tbs=cdr%3A1%2Ccd_min%3A1%2F01%2F2015%2Ccd_max%3A1%2F01%2F2015
我看到结果其实是只有2,如果我手动下载HTML文件,打开页面源搜索 id="resultStats" 我发现结果数确实是2个!
谁能帮我理解为什么在保存的 HTML 文件和 soup 项目中搜索相同的 id 标签会导致两个不同的数值结果?
*************** 更新 问题似乎是 requests.get 没有正确处理自定义日期范围。如果我将相同的 URL 与 selenium 一起使用,我会得到正确的答案
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(url)
content = driver.page_source
soup = bs4.BeautifulSoup(content)
elems = soup.select('#resultStats')
print(elems[0].getText())
答案是
2 results (0.09 seconds)
问题是这个方法好像比较麻烦,因为我需要在Firefox中打开页面...
有几件事导致了这个问题。首先,它需要 2 位数字的日期和月份部分,并且还需要一些流行浏览器的用户代理字符串。以下代码应该有效:
import requests, bs4
headers = {
"User-Agent":
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36"
}
payload = {'as_epq': 'James Clark', 'tbs':'cdr:1,cd_min:01/01/2015,cd_max:01/01/2015', 'tbm':'nws'}
r = requests.get("https://www.google.com/search", params=payload, headers=headers)
soup = bs4.BeautifulSoup(r.content, 'html5lib')
print soup.find(id='resultStats').text
添加到 Vikas 的回答中,Google 也将无法对某些用户代理使用 'custom date range'。也就是说,对于某些用户代理,Google 将只搜索 'recent' 结果而不是您指定的日期范围。
我没有检测到用户代理会打破自定义日期范围的明确模式。似乎包括语言是一个因素。
以下是一些破坏 cdr
的用户代理示例:
Mozilla/5.0 (Windows; U; Windows NT 6.1; fr-FR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27
Mozilla/4.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)
selenium
不需要,你要找的是:
soup.select_one('#result-stats nobr').previous_sibling
# About 10,700,000 results
代码和full 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": 'James Clark', # query
"hl": "en", # lang
"gl": "us", # country to search from
"tbm": "nws", # news filter
}
html = requests.get('https://www.google.com/search', headers=headers, params=params)
soup = BeautifulSoup(html.text, 'lxml')
# if used without "nobr" selector and previous_sibling it will return seconds as well: (0.41 secods)
number_of_results = soup.select_one('#result-stats nobr').previous_sibling
print(number_of_results)
# About 10,700,000 results
或者,您可以使用 SerpApi 中的 Google News Results API 来实现相同的目的。这是付费 API 和免费计划。
你的情况的不同之处在于你不必找到哪些选择器可以完成工作,或者弄清楚为什么其中一些不return你想要的数据他们也应该绕过阻止搜索引擎,并随着时间的推移维护它。
相反,您只需要迭代结构化 JSON 并快速获取您想要的数据。
为您的案例集成的代码:
import os
from serpapi import GoogleSearch
params = {
"engine": "google",
"q": 'James Clark',
"tbm": "nws",
"gl": "us",
"api_key": os.getenv("API_KEY"),
}
search = GoogleSearch(params)
results = search.get_dict()
number_of_results = results['search_information']['total_results']
print(number_of_results)
# 14300000
Disclaimer, I work for SerpApi.