zoukankan      html  css  js  c++  java
  • 关于scrapy下载文件重命名的办法以及对应url没有文件后缀的办法

    https://www.jianshu.com/p/d1bb28cbb6a8

    scrapy中负责下载文件的是class MyFilesPipeline(FilesPipeline)

    • 其中负责下载文件的方法是
    def file_path(self, request, response=None, info=None):
            ## start of deprecation warning block (can be removed in the future)
            def _warn():
                from scrapy.exceptions import ScrapyDeprecationWarning
                import warnings
                warnings.warn('FilesPipeline.file_key(url) method is deprecated, please use '
                              'file_path(request, response=None, info=None) instead',
                              category=ScrapyDeprecationWarning, stacklevel=1)
    
            # check if called from file_key with url as first argument
            if not isinstance(request, Request):
                _warn()
                url = request
            else:
                url = request.url
    
            # detect if file_key() method has been overridden
            if not hasattr(self.file_key, '_base'):
                _warn()
                return self.file_key(url)
            ## end of deprecation warning block
    
            media_guid = hashlib.sha1(to_bytes(url)).hexdigest()  # change to request.url after deprecation
            media_ext = os.path.splitext(url)[1]  # change to request.url after deprecation
            return 'full/%s%s' % (media_guid, media_ext)
    

      

    我们可以很清楚地看到 因为是下载的是文件,所以默认的response参数是为None的,因为一般来讲,文件的response就是我们下载的。我们待会说明response为None的坏处。
    所以,修改文件名的办法就很显然了。在return处做文章:return 的文件路径,用了两个变量media_guidmedia_ext

    1. 其中media_guid是一个将url进行哈希加密的文件,可以修改
    2. 另一个media_ext是什么呢: os.path.splitext(url)[1]这个函数是将url作切割,不同于py里的split函数,这个函数只返回两部分,示例如下
    import os
    path_01='D:/User/wgy/workplace/data/notMNIST_large.tar.gar'
    path_02='D:/User/wgy/workplace/data/notMNIST_large'
    root_01=os.path.splitext(path_01)
    root_02=os.path.splitext(path_02)
    print(root_01)
    print(root_02)
    

      

    结果:
    ('D:/User/wgy/workplace/data/notMNIST_large.tar', '.gar')
    ('D:/User/wgy/workplace/data/notMNIST_large', '')
    

      可以看到,就是在scrapy里这个函数就是获取后缀的。
    综上,文件名可以在这边修改。

    但是有一个问题,如果想要下载的文件的url是经过重定向,或者对应的url没有后缀呢。
    由于网页一般会将想要请求的文件类型放在response的头部信息 content-type里,我们可以通过获取content-type信息,在进行相应的操作。这样我们就需要找到调用file_path的函数

    def file_downloaded(self, response, request, info):
            path = self.file_path(request, response=response, info=info)
            buf = BytesIO(response.body)
            checksum = md5sum(buf)
            buf.seek(0)
            self.store.persist_file(path, buf, info)
            return checksum
    

      

    • file_downloaded里,第一行就是调用了file_path函数,而且根据命名规则,十分清晰。 我们只要对上述path 做一定的修改即可。
    • 因为file_downloaded是对文件进行下载,而file_path是对文件进行存储路径的安排的,所以file_downloaded这里的response我们是可以获取相关信息的。
      获取重定向后文件后缀的方法为:
      response.headers.get('Content-Disposition') 或者 response.headers.get('Content-Type') ,如果获取不到,可以改成content-disposition 或者 content-type,举个例子
      content-disposition可能得到的是这个:
      Content-Disposition: inline;filename=Vet%20Contract%20for%20Services.pdf,直接正则获取最后的文件路径

    color{red}{Content-Disposition} 是一个扩展协议,对得到的内容进行正则处理后,可以得到后缀,一般建议先用这个。但有的并不支持这种协议
    color{red}{Content-Type}一般网站都是支持的,但是它返回的文件类型可能没法直接使用,所以建议先使用上面的那个
    但是有一个问题,如果想要下载的文件的url是经过重定向,或者对应的url没有后缀呢。
    由于网页一般会将想要请求的文件类型放在response的头部信息 content-type里,我们可以通过获取content-type信息,在进行相应的操作。这样我们就需要找到调用file_path的函数


    作者:老鼠慎言
    链接:https://www.jianshu.com/p/d1bb28cbb6a8
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    tuple 元组及字典dict
    day 49 css属性补充浮动 属性定位 抽屉作业
    day48 选择器(基本、层级 、属性) css属性
    day47 列表 表单 css初识
    day 46 http和html
    day 45索引
    day 44 练习题讲解 多表查询
    day 40 多表查询 子查询
    day39 表之间的关联关系、 补充 表操作总结 where 、group by、
    day38 数据类型 约束条件
  • 原文地址:https://www.cnblogs.com/pythonClub/p/9858830.html
Copyright © 2011-2022 走看看