Python 网页抓取谷歌搜索结果
我正在一页一页地抓取谷歌学者搜索结果。在一定数量的页面之后,一个验证码弹出并中断我的代码。我读到谷歌限制了我每小时可以提出的请求。有办法绕过这个限制吗?我读了一些关于API的文章,但我不确定这是否有用 我感觉到了你的痛苦,因为我过去从谷歌上抓取过。为了完成我的工作,我尝试了以下几件事。这个列表是从最简单的技术到最难的技术排序的Python 网页抓取谷歌搜索结果,python,web-scraping,beautifulsoup,web-crawler,Python,Web Scraping,Beautifulsoup,Web Crawler,我正在一页一页地抓取谷歌学者搜索结果。在一定数量的页面之后,一个验证码弹出并中断我的代码。我读到谷歌限制了我每小时可以提出的请求。有办法绕过这个限制吗?我读了一些关于API的文章,但我不确定这是否有用 我感觉到了你的痛苦,因为我过去从谷歌上抓取过。为了完成我的工作,我尝试了以下几件事。这个列表是从最简单的技术到最难的技术排序的 每秒限制您的请求:谷歌和许多其他网站将每秒识别来自同一台机器的大量请求,并自动阻止它们,作为对您的防御措施。你所需要做的就是保持温和,例如,每1-5秒只做一次请求,以避
- 每秒限制您的请求:谷歌和许多其他网站将每秒识别来自同一台机器的大量请求,并自动阻止它们,作为对您的防御措施。你所需要做的就是保持温和,例如,每1-5秒只做一次请求,以避免很快被禁止
- 随机化您的睡眠时间:让您的代码睡眠1秒钟太容易被检测为脚本。让它在每次迭代中随机休眠一段时间。显示了如何将其随机化的示例
- 使用启用Cookie的web scraper库:如果您从头开始编写刮码,Google会注意到您的请求不会返回它收到的Cookie。使用一个好的库,例如来规避这个问题
- 使用多个IP地址:节流肯定会降低刮取吞吐量。如果你真的需要快速抓取数据,你需要使用几个IP地址以避免被禁止。有几家公司在互联网上以一定的价格提供这种服务。我使用过并且非常喜欢它们的质量、文档和客户支持
- 使用真正的浏览器:如果scraper不处理JavaScript或没有图形界面,一些网站会识别你的scraper。例如,使用具有的真实浏览器将解决此问题
你也可以看看,这是为纽约大学的网络搜索引擎课程编写的。它本身并不刮谷歌,但包含上述一些技术,如限制和随机分配睡眠时间。来自刮谷歌学者的个人经验。45秒足以避免验证码和机器人检测。我有一台铲运机在没有检测到的情况下运行了3天以上。如果您确实被标记,等待大约2小时就足以重新开始
谷歌没有为Scholarotate代理和用户代理提供API,以避免来自谷歌的阻止请求。我想知道您是否可以就如何设置
global\u config
和program\u logger
提供建议?我尝试了pip安装
,但对我来说不起作用。我在R中寻找一个解决方案,但我看到了您的Python解决方案,所以我正在努力让它发挥作用,尽管我的Python技能相当薄弱。另外,我想知道如何输入要搜索的关键字字符串?
class ScholarScrape():
def __init__(self):
self.page = None
self.last_url = None
self.last_time = time.time()
self.min_time_between_scrape = int(ConfigFile.instance().config.get('scholar','bot_avoidance_time'))
self.header = {'User-Agent':ConfigFile.instance().config.get('scholar','user_agent')}
self.session = requests.Session()
pass
def search(self, query=None, year_lo=None, year_hi=None, title_only=False, publication_string=None, author_string=None, include_citations=True, include_patents=True):
url = self.get_url(query, year_lo, year_hi, title_only, publication_string, author_string, include_citations, include_patents)
while True:
wait_time = self.min_time_between_scrape - (time.time() - self.last_time)
if wait_time > 0:
logger.info("Delaying search by {} seconds to avoid bot detection.".format(wait_time))
time.sleep(wait_time)
self.last_time = time.time()
logger.info("SCHOLARSCRAPE: " + url)
self.page = BeautifulSoup(self.session.get(url, headers=self.header).text, 'html.parser')
self.last_url = url
if "Our systems have detected unusual traffic from your computer network" in str(self.page):
raise BotDetectionException("Google has blocked this computer for a short time because it has detected this scraping script.")
return
def get_url(self, query=None, year_lo=None, year_hi=None, title_only=False, publication_string=None, author_string=None, include_citations=True, include_patents=True):
base_url = "https://scholar.google.com.au/scholar?"
url = base_url + "as_q=" + urllib.parse.quote(query)
if year_lo is not None and bool(re.match(r'.*([1-3][0-9]{3})', str(year_lo))):
url += "&as_ylo=" + str(year_lo)
if year_hi is not None and bool(re.match(r'.*([1-3][0-9]{3})', str(year_hi))):
url += "&as_yhi=" + str(year_hi)
if title_only:
url += "&as_yhi=title"
else:
url += "&as_yhi=any"
if publication_string is not None:
url += "&as_publication=" + urllib.parse.quote('"' + str(publication_string) + '"')
if author_string is not None:
url += "&as_sauthors=" + urllib.parse.quote('"' + str(author_string) + '"')
if include_citations:
url += "&as_vis=0"
else:
url += "&as_vis=1"
if include_patents:
url += "&as_sdt=0"
else:
url += "&as_sdt=1"
return url
def get_results_count(self):
e = self.page.findAll("div", {"class": "gs_ab_mdw"})
try:
item = e[1].text.strip()
except IndexError as ex:
if "Our systems have detected unusual traffic from your computer network" in str(self.page):
raise BotDetectionException("Google has blocked this computer for a short time because it has detected this scraping script.")
else:
raise ex
if self.has_numbers(item):
return self.get_results_count_from_soup_string(item)
for item in e:
item = item.text.strip()
if self.has_numbers(item):
return self.get_results_count_from_soup_string(item)
return 0
@staticmethod
def get_results_count_from_soup_string(element):
if "About" in element:
num = element.split(" ")[1].strip().replace(",","")
else:
num = element.split(" ")[0].strip().replace(",","")
return num
@staticmethod
def has_numbers(input_string):
return any(char.isdigit() for char in input_string)
class BotDetectionException(Exception):
pass
if __name__ == "__main__":
s = ScholarScrape()
s.search(**{
"query":"\"policy shaping\"",
# "publication_string":"JMLR",
"author_string": "gilboa",
"year_lo": "1995",
"year_hi": "2005",
})
x = s.get_results_count()
print(x)