使用Scrapy时不要等待文件下载
我有一个处理流程,它会从一个项目中获取网址并下载文件。问题是,我还有另一个流程,在这个流程中,我需要手动检查这个文件并添加一些信息。而我真的需要在文件下载之前就完成这个检查。
class VideoCommentPipeline(object):
def process_item(self, item, spider):
os.system("vlc -vvv %s > /dev/null 2>&1 &" % item['file'])
item['comment'] = raw_input('Your comment:')
return item
class VideoDownloadPipeline(object):
def process_item(self, item, spider):
video_basename = item['file'].split('/')[-1]
new_filename = os.path.join(VIDEOS_DIR, video_basename)
downloaded = False
for i in range(5):
try:
video = urllib2.urlopen(item['file']).read()
downloaded = True
break
except:
continue
if not downloaded:
raise DropItem("Couldn't download file from %s" % item)
f = open(new_filename, 'wb')
f.write(video)
f.close()
item['file'] = video_basename
return item
但是现在我总是得等着下一个项目,因为前一个项目的文件还没下载好。我更希望能先检查所有项目,然后再一起下载文件。那我该怎么做呢?
1 个回答
3
Scrapy 提供了一个叫做 媒体管道 的功能,可以用来满足你的需求。虽然这个功能的文档写得不太好,但它确实存在,并且在最近的 Scrapy 版本中可以使用。要理解它是怎么工作的,你需要看看代码,个人觉得还是挺直观的。你可以查看 图像管道 的接口,这样能帮助你理解媒体管道是如何运作的。
如果你想在下载每个视频之前先检查一下,可以写一些类似下面的代码(你需要根据你的项目字段名称进行调整)
from scrapy.contrib.pipeline.media import MediaPipeline
class VideoPipeline(MediaPipeline):
VIDEOS_DIR = "/stack/scrapy/video/video/store"
def get_media_requests(self, item, info):
"""
Evaluate file and, if you like it, download it.
"""
os.system("vlc -vvv %s > /dev/null 2>&1 &" % item['video_url'][0])
your_opinion = raw_input("how does it look?")
item["comment"] = your_opinion
if your_opinion == "hot":
# issue request download video
return Request(item["video_url"][0], meta={"item":item})
def media_downloaded(self, response, request, info):
"""
File is downloaded available as response.body save it.
"""
item = response.meta.get("item")
video = response.body
video_basename = item['title'][0]
new_filename = os.path.join(self.VIDEOS_DIR, video_basename)
f = open(new_filename, 'wb')
f.write(video)
f.close()