Google使用python抓取-请求:如何避免由于许多请求而被阻止?

时间:2018-08-21 17:25:44

标签: python python-2.7 web-scraping python-requests

对于一个学校项目,我需要获得200家公司的网址(基于列表)。我的脚本运行正常,但是当我在80号公司工作时,被Google封锁了。这是我得到的信息。

> Our systems have detected unusual traffic from your computer network. 
> This page checks to see if it's really you sending the requests, and
> not a robot.  <a href="#"
> onclick="document.getElementById('infoDiv').style.display='block'

我尝试了两种不同的方式来获取数据:

一个简单的例子:

for company_name in data:
     search = company_name
     results = 1
     page = requests.get("https://www.google.com/search?q={}&num={}".format(search, results))

     soup = BeautifulSoup(page.content, "html5lib")

以及更复杂的内容:

for company_name in data:
    search = company_name
    results = 1

    s = requests.Session()
    retries = Retry(total=3, backoff_factor=0.5)
    s.mount('http://', HTTPAdapter(max_retries=retries))
    s.mount('https://', HTTPAdapter(max_retries=retries))
    page = s.get("https://www.google.com/search?q={}&num={}".format(search, results))
    #time.sleep(.600)

    soup = BeautifulSoup(page.content, "html5lib")

但是我一遍又一遍地犯同样的错误。有什么办法可以解决这个问题?谢谢!

2 个答案:

答案 0 :(得分:0)

如果您只想确保每0.6秒才发出1个以上的请求,则只需睡觉即可,直到距离上一个请求至少0.6秒为止。

如果处理每个请求所花费的时间仅为0.6秒的一小部分,则可以取消注释代码中已有的行。但是,在循环的末尾而不是在中间进行操作可能更有意义:

for company_name in data:
    # blah blah
    page = s.get("https://www.google.com/search?q={}&num={}".format(search, results))
    soup = BeautifulSoup(page.content, "html5lib")
    # do whatever you wanted with soup
    time.sleep(.600)

如果处理花费0.6秒的时间,那么等待0.6秒就太长了。例如,如果有时花费0.1秒,有时花费1.0,那么您想在第一种情况下等待0.5秒,而在第二种情况下根本不等待,对吧?

在这种情况下,只需跟踪您上一次发出请求的时间,然后睡觉直到0.6秒:

last_req = time.time()
for company_name in data:
    # blah blah
    page = s.get("https://www.google.com/search?q={}&num={}".format(search, results))
    soup = BeautifulSoup(page.content, "html5lib")
    # do whatever you wanted with soup

    now = time.time()
    delay = last_req + 0.600 - now
    last_req = now
    if delay >= 0:
        time.sleep(delay)

如果您需要每0.6秒精确地发出一次 请求,或者尽可能接近该请求,则可以启动一个执行该请求的线程,并将结果扔到队列中,而另一个线程(可能是您的主线程)只是阻止将请求从该队列中弹出并进行处理。

但是我无法想象您为什么需要它。

答案 1 :(得分:0)

您可以尝试将用户代理标头调整为默认python requests以外的值。这样,我可以毫无问题地搜索https://www.sec.gov/rules/other/4-460list.htm的所有 949 家公司。

我的默认用户代理是:

print requests.utils.default_headers()

{'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.8.1'}

Google 可能检测为异常流量

user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14'
headers = {'User-Agent': user_agent,'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'}

for company_name in data:
    search = company_name
    results = 1
    page = requests.get("https://www.google.com/search?q={}&num={}".format(search, results), headers=headers)
    soup = BeautifulSoup(page.content, "html5lib")
    print company_name
    print soup.find('h3', attrs={'class':'r'}).text
    print soup.find('h3', attrs={'class':'r'}).find('a').attrs['href']