Python 残缺不全的产量逻辑被打破了
以下简单代码导致vBulletin论坛网站出现问题:Python 残缺不全的产量逻辑被打破了,python,scrapy,yield,Python,Scrapy,Yield,以下简单代码导致vBulletin论坛网站出现问题: class ForumSpider(CrawlSpider): ... rules = ( Rule(SgmlLinkExtractor(restrict_xpaths="//div[@class='threadlink condensed']"), callback='parse_threads'), ) def parse_threads(
class ForumSpider(CrawlSpider):
...
rules = (
Rule(SgmlLinkExtractor(restrict_xpaths="//div[@class='threadlink condensed']"),
callback='parse_threads'),
)
def parse_threads(self, response):
thread = HtmlXPathSelector(response)
# get the list of posts
posts = thread.select("//div[@id='posts']//table[contains(@id,'post')]/*")
# plist = []
for p in posts:
table = ThreadItem()
table['thread_id'] = (p.select("//input[@name='searchthreadid']/@value").extract())[0].strip()
string_id = p.select("../@id").extract() # returns a list
p_id = string_id[0].split("post")
table['post_id'] = p_id[1]
# plist.append(table)
# return plist
yield table
撇开xpath的一些漏洞不谈,当我使用yield运行这个程序时,我得到了非常奇怪的结果,对同一个线程id和帖子id进行了多次点击。类似于:
114763,1314728
114763,1314728
114763,1314728
114763,1314740
114763,1314740
114763,1314740
当我切换回与返回相同的逻辑时(在注释中),一切正常。我想这可能是发电机的一些基本错误,但我无法理解。为什么相同的帖子会被多次点击?为什么代码使用return而不是yield工作
gist中的完整代码片段。看起来像是缩进问题。以下操作应与使用列表和返回相同:
def parse_threads(self, response):
thread = HtmlXPathSelector(response)
# get the list of posts
posts = thread.select("//div[@id='posts']//table[contains(@id,'post')]/*")
for p in posts:
table = ThreadItem()
table['thread_id'] = (p.select("//input[@name='searchthreadid']/@value").extract())[0].strip()
string_id = p.select("../@id").extract() # returns a list
p_id = string_id[0].split("post")
table['post_id'] = p_id[1]
yield table
UPD:我已经修复并改进了parse_threads
方法的代码,现在应该可以工作了:
def parse_threads(self, response):
thread = HtmlXPathSelector(response)
thread_id = thread.select("//input[@name='searchthreadid']/@value").extract()[0].strip()
post_id = thread.select("//div[@id='posts']//table[contains(@id,'post')]/@id").extract()[0].split("post")[1]
# get the list of posts
posts = thread.select("//div[@id='posts']//table[contains(@id,'post')]/tr[2]")
for p in posts:
# getting user_name
user_name = p.select(".//a[@class='bigusername']/text()").extract()[0].strip()
# skip adverts
if 'Advertisement' in user_name:
continue
table = ThreadItem()
table['user_name'] = user_name
table['thread_id'] = thread_id
table['post_id'] = p.select("../@id").extract()[0].split("post")[1]
yield table
希望有帮助。看起来这是一个缩进问题。以下操作应与使用列表和返回相同:
def parse_threads(self, response):
thread = HtmlXPathSelector(response)
# get the list of posts
posts = thread.select("//div[@id='posts']//table[contains(@id,'post')]/*")
for p in posts:
table = ThreadItem()
table['thread_id'] = (p.select("//input[@name='searchthreadid']/@value").extract())[0].strip()
string_id = p.select("../@id").extract() # returns a list
p_id = string_id[0].split("post")
table['post_id'] = p_id[1]
yield table
UPD:我已经修复并改进了parse_threads
方法的代码,现在应该可以工作了:
def parse_threads(self, response):
thread = HtmlXPathSelector(response)
thread_id = thread.select("//input[@name='searchthreadid']/@value").extract()[0].strip()
post_id = thread.select("//div[@id='posts']//table[contains(@id,'post')]/@id").extract()[0].split("post")[1]
# get the list of posts
posts = thread.select("//div[@id='posts']//table[contains(@id,'post')]/tr[2]")
for p in posts:
# getting user_name
user_name = p.select(".//a[@class='bigusername']/text()").extract()[0].strip()
# skip adverts
if 'Advertisement' in user_name:
continue
table = ThreadItem()
table['user_name'] = user_name
table['thread_id'] = thread_id
table['post_id'] = p.select("../@id").extract()[0].split("post")[1]
yield table
希望能有帮助。啊,我很抱歉!缩进在运行的代码中是正确的。那只是复制和粘贴错误。好吧,那它应该可以工作。不要看到任何错误。你能给我看一下你的蜘蛛的全部代码吗?如果你也需要items.py,请告诉我。正如你所看到的,现在它非常简单。我昨天花了一整天的时间在这个问题上--我真的对收益率的问题束手无策。现在我在看它--它可能是生成器函数中的continue语句。在没有continue的情况下测试--同样的问题。10个唯一的ID返回/111个重复的项目返回。啊,我的道歉!缩进在运行的代码中是正确的。那只是复制和粘贴错误。好吧,那它应该可以工作。不要看到任何错误。你能给我看一下你的蜘蛛的全部代码吗?如果你也需要items.py,请告诉我。正如你所看到的,现在它非常简单。我昨天花了一整天的时间在这个问题上--我真的对收益率的问题束手无策。现在我在看它--它可能是生成器函数中的continue语句。在没有continue的情况下测试--同样的问题。10个具有退货的唯一ID/111个具有收益的重复项目。