我应该创建管道来用Scrapy保存文件吗?

17 投票
3 回答
16618 浏览
提问于 2025-04-16 23:57

我需要保存一个文件(.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

撰写回答