目前正在与其他学生一起参加网络抓取课程,我们应该向虚拟网站提出“获取”请求,解析并访问其他网站。
问题是,虚拟网站的内容只会持续几分钟而消失,内容会以一定的间隔恢复。在内容可用的时间内,每个人都试图发出“获取”请求,因此我只是挂起,直到每个人都清除,内容最终消失。所以我最终无法成功发出'get'请求:
import requests
from splinter import Browser
browser = Browser('chrome')
# Hangs here
requests.get('http://dummysite.ca').text
# Even if get is successful hangs here as well
browser.visit(parsed_url)
所以我的问题是,在得到回复之前,最快/最好的方法是做出无休止的并发“获取”请求?
答案 0 :(得分:1)
决定使用requests
或splinter
相关
了解keep-alive
阅读blocking-or-non-blocking
阅读timeouts
阅读errors-and-exceptions
如果您能够未挂起请求,您可以考虑重复请求,例如:
while True:
requests.get(...
if request is succesfull:
break
time.sleep(1)
答案 1 :(得分:1)
Gevent
提供了运行异步网络请求的框架。
它可以修补Python的标准库,以便requests
和splinter
等现有库可以开箱即用。
以下是基于上述代码生成10个并发请求并获得响应的简短示例。
from gevent import monkey
monkey.patch_all()
import gevent.pool
import requests
pool = gevent.pool.Pool(size=10)
greenlets = [pool.spawn(requests.get, 'http://dummysite.ca')
for _ in range(10)]
# Wait for all requests to complete
pool.join()
for greenlet in greenlets:
# This will raise any exceptions raised by the request
# Need to catch errors, or check if an exception was
# thrown by checking `greenlet.exception`
response = greenlet.get()
text_response = response.text
还可以使用map
和响应处理函数代替get
。
有关详细信息,请参阅gevent documentation。
答案 2 :(得分:1)
在这种情况下,并发性将无济于事,因为服务器似乎是限制因素。一种解决方案是发送具有超时间隔的请求,如果超过间隔,则在几秒钟后再次尝试请求。然后逐渐增加重试之间的时间,直到获得所需的数据。例如,您的代码可能如下所示:
import time
import requests
def get_content(url, timeout):
# raise Timeout exception if more than x sends have passed
resp = requests.get(url, timeout=timeout)
# raise generic exception if request is unsuccessful
if resp.status_code != 200:
raise LookupError('status is not 200')
return resp.content
timeout = 5 # seconds
retry_interval = 0
max_retry_interval = 120
while True:
try:
response = get_content('https://example.com', timeout=timeout)
retry_interval = 0 # reset retry interval after success
break
except (LookupError, requests.exceptions.Timeout):
retry_interval += 10
if retry_interval > max_retry_interval:
retry_interval = max_retry_interval
time.sleep(retry_interval)
# process response
如果需要并发,请考虑Scrapy项目。它使用Twisted框架。在Scrapy中,您可以将time.sleep
替换为reactor.callLater(fn, *args, **kw)
,或使用数百个中间件插件中的一个。
答案 3 :(得分:0)
如果远程服务器速度很慢,您可以告诉请求等待 永远为响应,通过传递None作为超时值然后 拿起一杯咖啡。
import requests
#Wait potentially forever
r = requests.get('http://dummysite.ca', timeout=None)
#Check the status code to see how the server is handling the request
print r.status_code
从2开始的Status codes意味着收到,理解和接受了请求。 200表示请求成功并返回信息。但503表示服务器过载或正在进行维护。
请求用于包含一个名为async的模块,该模块可以发送并发请求。它现在是一个名为grequests的独立模块 您可以使用它来无休止地发出并发请求,直到200响应:
import grequests
urls = [
'http://python-requests.org', #Just include one url if you want
'http://httpbin.org',
'http://python-guide.org',
'http://kennethreitz.com'
]
def keep_going():
rs = (grequests.get(u) for u in urls) #Make a set of unsent Requests
out = grequests.map(rs) #Send them all at the same time
for i in out:
if i.status_code == 200:
print i.text
del urls[out.index(i)] #If we have the content, delete the URL
return
while urls:
keep_going()
答案 4 :(得分:-1)