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
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    c:forTokens标签循环输出
    jsp转long类型为date,并且格式化
    spring中@Param和mybatis中@Param使用区别(暂时还没接触)
    734. Sentence Similarity 有字典数组的相似句子
    246. Strobogrammatic Number 上下对称的数字
    720. Longest Word in Dictionary 能连续拼接出来的最长单词
    599. Minimum Index Sum of Two Lists两个餐厅列表的索引和最小
    594. Longest Harmonious Subsequence强制差距为1的最长连续
    645. Set Mismatch挑出不匹配的元素和应该真正存在的元素
    409. Longest Palindrome 最长对称串
  • 原文地址:https://www.cnblogs.com/pythonClub/p/9858830.html
Copyright © 2011-2022 走看看