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參數(shù)是為None的,因為一般來講,文件的response就是我們下載的稚机。我們待會說明response為None的壞處幕帆。
所以,修改文件名的辦法就很顯然了抒钱。在return處做文章:return 的文件路徑蜓肆,用了兩個變量media_guid
和media_ext
- 其中
media_guid
是一個將url進行哈希加密的文件颜凯,可以修改。 - 另一個
media_ext
是什么呢:os.path.splitext(url)[1]
這個函數(shù)是將url作切割仗扬,不同于py里的split
函數(shù)症概,這個函數(shù)只返回兩部分,示例如下
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)
結(jié)果:
('D:/User/wgy/workplace/data/notMNIST_large.tar', '.gar')
('D:/User/wgy/workplace/data/notMNIST_large', '')
可以看到早芭,就是在scrapy里這個函數(shù)就是獲取后綴的彼城。
綜上,文件名可以在這邊修改退个。
但是有一個問題募壕,如果想要下載的文件的url是經(jīng)過重定向,或者對應的url沒有后綴呢语盈。
由于網(wǎng)頁一般會將想要請求的文件類型放在response的頭部信息 content-type里舱馅,我們可以通過獲取content-type信息,在進行相應的操作刀荒。這樣我們就需要找到調(diào)用file_path
的函數(shù)
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
里代嗤,第一行就是調(diào)用了file_path
函數(shù),而且根據(jù)命名規(guī)則缠借,十分清晰干毅。 我們只要對上述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
,直接正則獲取最后的文件路徑
是一個擴展協(xié)議霹疫,對得到的內(nèi)容進行正則處理后拱绑,可以得到后綴综芥,一般建議先用這個丽蝎。但有的并不支持這種協(xié)議
一般網(wǎng)站都是支持的,但是它返回的文件類型可能沒法直接使用膀藐,所以建議先使用上面的那個