我想从一个每隔一段时间刷新自己的列表中一次提取一个代理,我对此没有任何问题。你知道吗
有些代理不好,我希望使用列表中的下一个代理。这就是我的生成器所在,但是,当我第一次调用a.next()时,第二次调用它时,我可以得到相同的值!你知道吗
很明显,我在理解发电机的工作原理时,肯定遗漏了一个关键部分。你知道吗
我的生成器代码位于ProxyHandler
类中:
class ProxyHandler:
def __init__(self):
self.proxies = list()
self.current = dict()
def get_proxies(self):
""" Retrieves proxies """
def __len__(self):
return len(self.proxies)
def yield_proxy(self):
if not self.proxies:
print 'Created new proxy list'
self.get_proxies() # This populates self.proxies which is a list of tuples where the 0th element is the host and the 1st element is the port
for p in self.proxies:
try:
proxy = {'http': 'http://%s:%s' % (p[0], p[1])} # Formatted to python's request lib proxy format
self.current = proxy
yield proxy
except StopIteration:
print 'Reached end of proxy list'
self.current = {}
self.get_proxies()
yield self.yield_proxy()
使用方法:
def get_response(self, url):
proxy = self.proxy_handler.current
if proxy == {}:
proxy = self.proxy_handler.yield_proxy().next()
print 'Current proxy -', proxy
response = url_request(url, proxy=proxy) # url_request() is basically a modified version of python's requests
print response
if response: # url_request() returns true if status code == 200
return response, proxy
gen = self.proxy_handler.yield_proxy()
gen.next()
return self.get_ebay_response(url)
每次都要重新创建生成器:
新的生成器从头开始;单独的生成器不共享状态。将生成器存储在某个位置,然后重用该对象以获取新值。你知道吗
您也许可以将生成器对象作为属性存储在
self
:我使用^{} function 使您的代码与python3保持向前兼容(您迟早要切换到python3,python2现在是一种遗留语言)。你知道吗
接下来,生成器将尝试捕获永远不会抛出的异常:
在
try
中没有被访问的生成器;您将该作业交给了self.proxies
上的for
循环,for
已经知道如何处理迭代器(它将捕获StopIterator
来结束循环)。不管怎样,self.proxies
只是一个列表。你知道吗如果你想让循环在你的代理上循环,在一个无休止的
while True
循环中这样做:我不知道你为什么认为你需要清除那里的
self.current
,然后重新获取代理。生成器上的元组从未更改,所以为什么要重新获取?并且当前代理仍然有效,即使您确实从顶部再次启动循环。我会放弃最后三行。你知道吗您可以进一步简化代码。生成器没有长度,因此不需要
__len__
方法。该方法最多只能生成错误的信息;在开始迭代之前,self.proxies
属性是空的,因此对象的长度从0开始。完全放弃这个方法。你知道吗接下来,可以为对象提供一个
__iter__
方法来生成生成器:这使得整个
ProxyHandler
实例成为一个iterable,只需使用iter(self.proxy_handler)
而不是self.proxy_handler.yield_proxy()
就可以让生成器生成所有这些值。你知道吗最后但并非最不重要的一点是,您可以对整个过程使用生成器表达式,再加上^{} 使迭代器无止境。但是,您必须删除
current
属性,但这并不重要,因为当生成器生成当前对象时,实际上并不需要该属性:生成器表达式生成相同类型的对象。你知道吗
这一切仍然需要
iter(self.proxy_generator)
;您可以通过让__iter__
返回self
,并添加一个next()
方法,使实例迭代器(而不是iterable);在第一次调用时,将上面的生成器表达式移动到一个属性,然后将next()
调用传递到该属性以生成值:现在可以使用“下一步”(self.proxy\u处理程序)每次:
相关问题 更多 >
编程相关推荐