Google 翻译 API id 阻塞 ip 地址太多请求

Google Translation API id blocking ip address for too many requests

我正在设置一个 Django 视图,从 API 请求产品数据,使用 BeautifulSoup 解析它们,应用 googletrans 模块并保存响应进入我的 Postgresql 数据库。

昨天一切正常,直到突然,Google 因一次太多请求而阻止访问我的 IP 地址..

我刚刚打开我的 LTE 来更改我的 IP 地址并且成功了。

但是现在,为了确保这个 IP 地址不会再次发生这种情况,我需要找到一种方法来批量调用 googletrans API 或任何其他可以阻止的解决方案我不会再被屏蔽了。

这是我的观点:

from bs4 import BeautifulSoup
from googletrans import Translator
import requests
import json


def api_data(request):
    if request.GET.get('mybtn'):  # to improve, == 'something':
        resp_1 = requests.get(
            "https://www.headout.com/api/public/v1/product/listing/list-by/city?language=fr&cityCode=PARIS&limit=5000&currencyCode=CAD",
            headers={
                "Headout-Auth": HEADOUT_PRODUCTION_API_KEY
            })
        resp_1_data = resp_1.json()
        base_url_2 = "https://www.headout.com/api/public/v1/product/get/"

        translator = Translator()

        for item in resp_1_data['items']:
            print('translating item {}'.format(item['id']))
            # concat ID to the URL string
            url = '{}{}'.format(base_url_2, item['id'] + '?language=fr')

            # make the HTTP request
            resp_2 = requests.get(
                url,
                headers={
                    "Headout-Auth": HEADOUT_PRODUCTION_API_KEY
                })
            resp_2_data = resp_2.json()

            descriptiontxt = resp_2_data['contentListHtml'][0]['html'][0:2040] + ' ...'

            #Parsing work
            soup = BeautifulSoup(descriptiontxt, 'lxml')
            parsed = soup.find('p').text

            #Translation doesn't work
            translation = translator.translate(parsed, dest='fr')

            titlename = item['name']
            titlefr = translator.translate(titlename, dest='fr')

            destinationname = item['city']['name']
            destinationfr = translator.translate(destinationname, dest='fr')

            Product.objects.get_or_create(
                title=titlefr.text,
                destination=destinationfr.text,
                description=translation.text,
                link=item['canonicalUrl'],
                image=item['image']['url']
            )

    return render(request, "form.html")

如何在 Batch 中调用 Google 翻译 API?或者还有其他解决方案吗?

请帮忙。

编辑

基于@ddor254 我应该把:time.sleep(2)?

这是我想出来的,可以吗?

  Product.objects.get_or_create(
      title=titlefr.text,
      destination=destinationfr.text,
      description=translation.text,
      link=item['canonicalUrl'],
      image=item['image']['url']
  )time.sleep(2) #here

或者像这样:

resp_1 = requests.get(
            "https://www.headout.com/api/public/v1/product/listing/list-by/city?language=fr&cityCode=PARIS&limit=5000&currencyCode=CAD",
            headers={
                "Headout-Auth": HEADOUT_PRODUCTION_API_KEY
            }, time.sleep(2)) #here

只是想确保它是正确的方法,然后再冒着让这个新 IP 也被阻止的风险。

我建议你阅读来自 MDN 的这篇文章:https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429

如果这是您得到的响应,请尝试查看响应 object 中的 header Retry-After

因此添加睡眠或其他延迟方法,其值 header 可能会解决您的问题。

尝试在连续查询之间添加延迟(使用睡眠)并尝试使用数字来查看适合您的方法。每对翻译后延迟 2 秒,每 10 对延迟 15 秒对我来说很好。

我也因为并发请求太多而被屏蔽了。通常在 500 个并发请求后总是被阻塞。我所做的是在每 100 个并发请求后设置 60 秒的超时。它可能看起来很长,但它确实有效。您也可以通过 45 秒的超时来实现这一点,但我将其设置为 60 只是为了确保。

这是一个例子

class GoogleAPI():

    def __init__(self):
        self.limit_before_timeout = 100
        self.timeout = 60

    def translate(self, source):
        translation = translator.translate(source, dest="ar")
        translation = translation.__dict__['text']
        if translation != "" and translation is not None:
            return translation

    def process(self):
        i = 0
        print("initiation")
        for t in list_of_data:
            if i < self.limit_before_timeout:
                i += 1
                self.translate(t)
            else:
                i = 0
                print("100 words added")
                time.sleep(self.timeout)
        print("All done")

我的 IP 在约 450 个并发连接后被阻止。我正在使用 php for 循环来翻译我的文本数组。

所以,我更改了我的 IP 地址,并更改了每隔 x 秒等待一次的代码。

我在 For 循环中的代码($i 是 for 循环的值):

if ($i % 100 == 0 && $i!=0) {
    //wait 60 seconds every 100
    usleep(60000000);   // 60 seconds
    echo str_pad("XX--> WAITING 60 SECONDS<br>",4096);
}               
else 
if ($i % 10 == 0  && $i!=0) {
    //wait 15 seconds every 10
     usleep(15000000); // 15 seconds
     echo str_pad("XX--> WAITING 15 SECONDS<br>",4096);
}
else    
if ($i % 2 == 0  && $i!=0) {
    //wait 2 seconds every 2
     usleep(2000000); // 2 seconds
     echo str_pad("XX--> WAITING 2 SECONDS<br>",4096);
}