我正在建立一个Django
视图,该视图从API请求产品数据,用BeautifulSoup
进行解析,应用googletrans
模块并将响应保存到我的Postgresql数据库中。 / p>
昨天一切正常,直到突然之间,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¤cyCode=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")
如何批量调用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¤cyCode=CAD",
headers={
"Headout-Auth": HEADOUT_PRODUCTION_API_KEY
}, time.sleep(2)) #here
只想确保以正确的方式进行操作,然后再冒获取新IP的风险。
答案 0 :(得分:1)
由于许多并发请求,我也被阻止了。通常在并发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")
答案 1 :(得分:0)
我建议您阅读MDN上的这篇文章:https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429
如果这是您得到的响应,请尝试查看响应对象中的标题Retry-After
。
因此添加带有该标头值的sleep或其他延迟方法可能会解决您的问题。
答案 2 :(得分:0)
尝试在连续查询之间添加延迟(使用睡眠),然后尝试数字以了解最适合您的方法。每对翻译后延迟2秒,每翻译10秒后延迟15秒,对我来说很好。
答案 3 :(得分:0)
在大约 450 个并发连接后,我的 IP 被阻止。我正在使用 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);
}