imn*_*mns 12 python django scrapy
我正在使用scrapy来抓取网站.该网站每页有15个列表,然后有一个下一个按钮.我遇到了一个问题,在我完成解析管道中的所有列表之前,我正在调用下一个链接的请求.这是我的蜘蛛的代码:
class MySpider(CrawlSpider):
name = 'mysite.com'
allowed_domains = ['mysite.com']
start_url = 'http://www.mysite.com/'
def start_requests(self):
return [Request(self.start_url, callback=self.parse_listings)]
def parse_listings(self, response):
hxs = HtmlXPathSelector(response)
listings = hxs.select('...')
for listing in listings:
il = MySiteLoader(selector=listing)
il.add_xpath('Title', '...')
il.add_xpath('Link', '...')
item = il.load_item()
listing_url = listing.select('...').extract()
if listing_url:
yield Request(urlparse.urljoin(response.url, listing_url[0]),
meta={'item': item},
callback=self.parse_listing_details)
next_page_url = hxs.select('descendant::div[@id="pagination"]/'
'div[@class="next-link"]/a/@href').extract()
if next_page_url:
yield Request(urlparse.urljoin(response.url, next_page_url[0]),
callback=self.parse_listings)
def parse_listing_details(self, response):
hxs = HtmlXPathSelector(response)
item = response.request.meta['item']
details = hxs.select('...')
il = MySiteLoader(selector=details, item=item)
il.add_xpath('Posted_on_Date', '...')
il.add_xpath('Description', '...')
return il.load_item()
Run Code Online (Sandbox Code Playgroud)
这些线是问题所在.就像我之前说过的那样,它们在蜘蛛爬完当前页面之前就被执行了.在网站的每个页面上,这导致我的列表中只有3个被发送到管道.
if next_page_url:
yield Request(urlparse.urljoin(response.url, next_page_url[0]),
callback=self.parse_listings)
Run Code Online (Sandbox Code Playgroud)
这是我的第一个蜘蛛,可能是我的设计缺陷,有更好的方法吗?
请参阅下面的 EDIT 2 部分的更新答案(2017 年 10 月 6 日更新)
\n\n您使用产量有什么具体原因吗?.next()
Yield 将返回一个生成器,当调用该生成器时,该生成器将返回 Request 对象。
yield
将您的陈述更改为return
陈述,事情应该按预期进行。
这是生成器的示例:
\n\nIn [1]: def foo(request):\n ...: yield 1\n ...: \n ...: \n\nIn [2]: print foo(None)\n<generator object foo at 0x10151c960>\n\nIn [3]: foo(None).next()\nOut[3]: 1\n
Run Code Online (Sandbox Code Playgroud)\n\n编辑:
\n\n更改您的def start_requests(self)
函数以使用该follow
参数。
return [Request(self.start_url, callback=self.parse_listings, follow=True)]\n
Run Code Online (Sandbox Code Playgroud)\n\n编辑2:
\n\n从2017-05-18发布的Scrapy v1.4.0开始,现在建议使用response.follow
而不是scrapy.Request
直接创建对象。
从发行说明来看:
\n\n\n\n\n有\xe2\x80\x99s一个新的response.follow方法来创建请求;现在,这是在 Scrapy 蜘蛛中创建请求的推荐方法。这种方法可以更容易地编写正确的爬虫程序;与直接创建 scrapy.Request 对象相比,response.follow 有几个优点:
\n\n\n
\n- 它处理相对 URL;
\n- 它可以与非 UTF8 页面上的非 ASCII URL 正常工作;
\n- 除了绝对和相对 URL 之外,它还支持选择器;对于元素,它还可以提取它们的 href 值。
\n
因此,对于上面的OP,将代码更改为:
\n\n next_page_url = hxs.select(\'descendant::div[@id="pagination"]/\'\n \'div[@class="next-link"]/a/@href\').extract()\n if next_page_url:\n yield Request(urlparse.urljoin(response.url, next_page_url[0]),\n callback=self.parse_listings)\n
Run Code Online (Sandbox Code Playgroud)\n\n到:
\n\n next_page_url = hxs.select(\'descendant::div[@id="pagination"]/\'\n \'div[@class="next-link"]/a/@href\')\n if next_page_url is not None:\n yield response.follow(next_page_url, self.parse_listings)\n
Run Code Online (Sandbox Code Playgroud)\n