Python 使用Scrapy:如何从一些提取的链接下载pdf文件

Python 使用Scrapy:如何从一些提取的链接下载pdf文件,python,web-scraping,Python,Web Scraping,我已经创建了从网站中提取一些链接的代码(PDF链接),现在我需要下载这些PDF文件,但我正在努力解决如何做到这一点。代码如下: 进口羊瘙痒 第5类(刮痕蜘蛛): name=“全部5” 起始URL=[ 'https://www.alloschool.com/course/alriadhiat-alaol-ibtdaii', ] def解析(自我,响应): 对于response.css('.default.er').xpath('@href').extract()中的链接: url=respons

我已经创建了从网站中提取一些链接的代码(PDF链接),现在我需要下载这些PDF文件,但我正在努力解决如何做到这一点。代码如下:


进口羊瘙痒
第5类(刮痕蜘蛛):
name=“全部5”
起始URL=[
'https://www.alloschool.com/course/alriadhiat-alaol-ibtdaii',
]
def解析(自我,响应):
对于response.css('.default.er').xpath('@href').extract()中的链接:
url=response.url
path=response.css('ol.breadcrumb li a::text').extract()
下一个链接=response.urljoin(链接)
产生scrapy.Request(下一个链接,callback=self.parse,meta={'url':url,'path':path})
def parse_det(自我,响应):
def extract_with_css(查询):
返回response.css(query.get)(默认值=“”).strip()
屈服{
“路径”:response.meta['path'],
“finallink”:使用css提取内容(“a.btn.btn primary::attr(href)”,
“url”:response.meta['url']
}
我需要下载的链接是“finallink”


如何解决此问题?

在“设置”中,您必须激活管道

ITEM_PIPELINES = {'scrapy.pipelines.files.FilesPipeline': 1}
和下载文件的文件夹

'FILES_STORE' = '.'
它将下载到
文件\u STORE/full

当您生成数据时,必须使用name
files\u url

yield {
    'file_urls': [extract_with_css('a.btn.btn-primary::attr(href)')]
    # ... rest ...
}
即使您有一个文件要下载,它也必须是列表

它应该将PDF下载到具有唯一名称的文件中,您可以在字段
files


刮伤文件:


编辑:独立代码-您可以复制并运行,而无需创建项目

#!/usr/bin/env python3

import scrapy

class MySpider(scrapy.Spider):

    name = 'myspider'

    start_urls = [
          'https://www.alloschool.com/course/alriadhiat-alaol-ibtdaii',
    ]

    def parse(self, response):

        for link in response.css('.default .er').xpath('@href').extract():
             url = response.url
             path = response.css('ol.breadcrumb li a::text').extract()
             next_link = response.urljoin(link)
             yield scrapy.Request(next_link, callback=self.parse_det, meta={'url': url, 'path': path})

    def parse_det(self, response):

        def extract_with_css(query):
            return response.css(query).get(default='').strip()

        yield {
            'path':response.meta['path'],
            'file_urls': [extract_with_css('a.btn.btn-primary::attr(href)')],
            'url':response.meta['url']
        }


from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0',

    # save in file as CSV, JSON or XML
    'FEED_FORMAT': 'csv',     # csv, json, xml
    'FEED_URI': 'output.csv', # 

    # download files to `FILES_STORE/full`
    # it needs `yield {'file_urls': [url]}` in `parse()`
    'ITEM_PIPELINES': {'scrapy.pipelines.files.FilesPipeline': 1},
    'FILES_STORE': '.',
})
c.crawl(MySpider)
c.start()

在设置中,您必须激活管道

ITEM_PIPELINES = {'scrapy.pipelines.files.FilesPipeline': 1}
和下载文件的文件夹

'FILES_STORE' = '.'
它将下载到
文件\u STORE/full

当您生成数据时,必须使用name
files\u url

yield {
    'file_urls': [extract_with_css('a.btn.btn-primary::attr(href)')]
    # ... rest ...
}
即使您有一个文件要下载,它也必须是列表

它应该将PDF下载到具有唯一名称的文件中,您可以在字段
files


刮伤文件:


编辑:独立代码-您可以复制并运行,而无需创建项目

#!/usr/bin/env python3

import scrapy

class MySpider(scrapy.Spider):

    name = 'myspider'

    start_urls = [
          'https://www.alloschool.com/course/alriadhiat-alaol-ibtdaii',
    ]

    def parse(self, response):

        for link in response.css('.default .er').xpath('@href').extract():
             url = response.url
             path = response.css('ol.breadcrumb li a::text').extract()
             next_link = response.urljoin(link)
             yield scrapy.Request(next_link, callback=self.parse_det, meta={'url': url, 'path': path})

    def parse_det(self, response):

        def extract_with_css(query):
            return response.css(query).get(default='').strip()

        yield {
            'path':response.meta['path'],
            'file_urls': [extract_with_css('a.btn.btn-primary::attr(href)')],
            'url':response.meta['url']
        }


from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0',

    # save in file as CSV, JSON or XML
    'FEED_FORMAT': 'csv',     # csv, json, xml
    'FEED_URI': 'output.csv', # 

    # download files to `FILES_STORE/full`
    # it needs `yield {'file_urls': [url]}` in `parse()`
    'ITEM_PIPELINES': {'scrapy.pipelines.files.FilesPipeline': 1},
    'FILES_STORE': '.',
})
c.crawl(MySpider)
c.start()

scrapy doc:scrapy doc:Thank you help@furas。我尝试了你向我建议的内容,它只下载了主链接中的文件:###,但在代码中,有一个指向另一个链接的链接,它必须从该链接获取finallink pdf('a.btn.btn primary::attr(href))“我不理解你的问题。如果你有到另一个页面的链接,那么使用
Request()
获取此页面并进行解析-然后获取到PDF的链接,您在
yield
中使用该链接是的,我就是这么做的,但我仍然没有在我的文件夹中保存任何PDF文件:/需要更正的两件事:(1)
文件\u URL
必须是列表-即使您有一个文件要下载。(2)它还需要
FILE\u STORE
和文件夹的名称来下载文件。它将下载到
FILE\u STORE/full
。我添加了完整的工作代码作为答案。它为我下载PDF。你可以不创建项目就运行它。非常感谢,它现在可以工作了!顺便问一下,有没有可能用它们原来的名称保存文件从网站获取,因为这里的文件是用随机字符保存的。感谢您的帮助@furas。我尝试了您向我建议的内容,它只下载了主链接中的文件:##,但在代码中,有一个链接指向另一个链接,它必须从该链接获取最终的pdf('a.btn.btn primary::attr(href)'“我不理解你的问题。如果你有到另一个页面的链接,那么使用
Request()
获取此页面并进行解析-然后获取到PDF的链接,您在
yield
中使用该链接是的,我就是这么做的,但我仍然没有在我的文件夹中保存任何PDF文件:/需要更正的两件事:(1)
文件\u URL
必须是列表-即使您有一个文件要下载。(2)它还需要
FILE\u STORE
和文件夹的名称来下载文件。它将下载到
FILE\u STORE/full
。我添加了完整的工作代码作为答案。它为我下载PDF。你可以不创建项目就运行它。非常感谢,它现在可以工作了!顺便问一下,有没有可能用它们原来的名称保存文件从网站获取,因为这里的文件是用随机字符保存的。