【发布时间】:2019-09-21 18:26:28
【问题描述】:
我要做的是抓取多个页面并在单个数组中产生结果。
我找到了this post,它描述了如何抓取多个页面并从每个抓取的页面中生成文本。
我提到了这种方法(并对其进行了一些修改),这是我的蜘蛛看起来像......
from scrapy import Request
from test_project.items import PriceSpiderItem
class RoomsSpider(scrapy.Spider):
name = 'rooms'
allowed_domains = ['sample.com']
start_urls = ['http://sample.com/rooms']
def parse(self, response):
for resource in response.xpath('.//*[@class="sample"]'):
item = PriceSpiderItem()
item['result'] = resource.xpath("text()").extract_first()
yield item
nextUrl = response.xpath('//*[@label="Next"]/@href').extract_first()
if(nextUrl is not None):
absoluteNextUrl = response.urljoin(nextUrl)
yield Request(url=absoluteNextUrl, callback=self.parse)
但是,使用这种方法,结果将看起来像...
{
"items" : [
{"result": "blah blah"},
{"result": "blah blah blah blah blah"},
{"result": "blah blah blah blah"},
...
etc.
...
{"result": "blah blah blah blah blah"},
{"result": "blah blah blah"}
]
}
这并不是我的目标。理想情况下,结果将在单个数组中,例如...
{
"items" : [
"blah blah",
"blah blah blah blah blah",
"blah blah blah blah",
...
"blah blah blah blah blah",
"blah blah blah"
]
}
但是,我不确定它是否可以实现。
据我了解,Scrapy 是非阻塞的,所以我可以将结果存储在一个全局变量中,并在蜘蛛爬取所有页面后生成它。
(也就是说,我不喜欢使用全局变量,因为随着应用程序变得越来越大,维护起来可能会很困难)
我们将不胜感激。
附言
@Wim Hermans 给了我有趣的方法(谢谢!)。
其中,将有可能将结果存储在一个带有ItemPipeline的文件中,并在所有页面被爬取后生成它。
这看起来很有希望,但如果 Spider 在 scrapyrt(或类似的东西)上运行以作为 REST API 端点工作,我不确定如何处理并发问题。
# 1. Client A makes a request
# 2. Spider receives Client A's request
# 3. Client B makes a request
# 4. Spider receives Client B's request
# 5. Spider fulfills Client B's request, saves the result in "result.csv"
# 6. Spider fulfills Client A's request, updates "result.csv" with Client A's request
# 7. Spider responses with "result.csv" for bot Client A and B
Scrapy 是非阻塞的,所以我想可能会发生这样的情况
附言
如果你必须yield 结果,@Wim Hermans 提出的第一个解决方案可能是最好的解决方案(但要小心内存使用)
【问题讨论】: