我应该创建管道来用Scrapy保存文件吗?
我需要保存一个文件(.pdf),但我不太确定该怎么做。我想保存.pdf文件,并且希望它们的存储方式能像我从网站上抓取的那样有条理,放在不同的文件夹里。
根据我的理解,我需要建立一个流程(pipeline),但是我了解到流程主要是用来保存“项目”,而“项目”其实就是一些基本的数据,比如字符串或数字。那么,保存文件算不算是使用流程的正确方式呢?还是说我应该直接在爬虫(spider)里保存文件呢?
3 个回答
4
这是个非常适合这个工作的工具。Scrapy的工作方式是,它有一些叫做“爬虫”的东西,这些爬虫可以把网页上的内容转化为有结构的数据(也就是“项目”)。而管道则是后处理的部分,它们使用和爬虫一样的异步技术,所以非常适合用来获取媒体文件。
在你的情况下,你首先需要在爬虫中提取PDF文件的位置,然后在管道中获取这些文件,最后再用另一个管道来保存这些项目。
9
有一个叫做FilesPipeline的工具,你可以直接使用它,前提是你已经有了文件的链接。这个链接展示了如何使用 FilesPipeline:
https://groups.google.com/forum/print/msg/scrapy-users/kzGHFjXywuY/O6PIhoT3thsJ
18
是的,也不是。如果你获取一个pdf文件,它会被存储在内存中,但如果这些pdf文件不大到占满你的可用内存,那就没问题。
你可以在爬虫的回调函数中保存这个pdf:
def parse_listing(self, response):
# ... extract pdf urls
for url in pdf_urls:
yield Request(url, callback=self.save_pdf)
def save_pdf(self, response):
path = self.get_path(response.url)
with open(path, "wb") as f:
f.write(response.body)
如果你选择在管道中处理:
# in the spider
def parse_pdf(self, response):
i = MyItem()
i['body'] = response.body
i['url'] = response.url
# you can add more metadata to the item
return i
# in your pipeline
def process_item(self, item, spider):
path = self.get_path(item['url'])
with open(path, "wb") as f:
f.write(item['body'])
# remove body and add path as reference
del item['body']
item['path'] = path
# let item be processed by other pipelines. ie. db store
return item
[1] 另一种方法是只存储pdf的链接,然后用其他方式去获取这些文件,而不是把它们放到内存里。(比如使用 wget
)