Я новичок в питоне и скрапе.Недавно я попытался отсканировать видео-сайт, который содержит более 3000 страниц, и каждая страница содержит 20 видео.Я использую scrapy
для получения URL-адресов (включая источник видео и следующую страницу) и requests
для загрузки видео.Проблема в том, что скрипт работает без ошибок, но скорость сканирования довольно низкая (около 4 страниц / мин).Я полагаю, это связано с тем, что scrapy блокирует следующий запрос или приостанавливает процесс загрузки из-за загрузки видео?Если да, то можно ли как-нибудь улучшить скорость копирования вместо написания другого скрипта, используя multithreading
?Вот мои сценарии:
setting.py:
BOT_NAME = 'video'
SPIDER_MODULES = ['video.spiders']
NEWSPIDER_MODULE = 'video.spiders'
LOG_LEVEL= 'DEBUG'
DUPEFILTER_CLASS= 'video.custom_filters.ViewKeyFilter'
DOWNLOAD_DELAY= 1
ITEM_PIPELINES= {'video.pipelines.VideoPipeline': 1,
'video.pipelines.Duplicates_Pipeline':300}
FILES_STORE= '/root/OneDrive/HDvideo'
custom_filters.py
class ViewKeyFilter(RFPDupeFilter):
def __init__(self,path=None,debug=False):
self.urls_seen = set()
RFPDupeFilter.__init__(self,path,debug)
def request_seen(self, request):
if 'viewkey=' in request.url:
pattern = re.compile(r'viewkey=(\w*)')
if pattern.search(request.url).group(1) in self.urls_seen:
return True
else:
self.urls_seen.add(request.url)
spider.py
class videoSpider(scrapy.Spider):
name = 'video'
def start_requests(self):
url = "http://video.com/v.php?next=watch&page=1"
yield Request(url,callback=self.parse,headers=headers,dont_filter=True)
def parse(self, response):
doc = HTML(html=response.text)
if doc.find('a:contains(">")'):
yield Request('http://video.com/v.php' + doc.find('a:contains(">")')[0].attrs['href'],
callback=self.parse, headers=headers,dont_filter=True)
for video_box in doc.find('div.listchannel'):
title = video_box.find('a[target="blank"]')[0].find('img')[0].attrs['title']
if not any(keyword in title for keyword in filterTitle):
SDURL = video_box.find('a[target="blank"]')[0].attrs['href']
if 'viewkey=' in SDURL:
if video_box.find('div.hd-video'):
vkey = pattern.search(SDURL).group(1) # Handling HD videos
yield Request('http://video.com/video_hd.php?viewkey={}'.format(vkey),
callback=self.parse_videoPage, headers=headers, cookies=cookies[random.randint(0,len(dummy_cookie) -1)])
else:
yield Request(SDURL,callback=self.parse_videoPage,
headers=headers)
def parse_videoPage(self,response):
if 'video_missing' not in response.url:
doc = HTML(html=response.text)
title = doc.find('#video-title')[0].text
src = doc.find('source')[0].attrs['src']
item = VideoItem()
item['title'] = title
item['src'] = src
item['vkey'] = pattern.search(response.url).group(1)
self.logger.info('Return item. Title:{} src:{}'.format(title,src))
yield item
конвейеры.py
class VideoPipeline(MediaPipeline):
def process_item(self, item,spider):
if item['src']:
try:
r =requests.get(item['src'],stream=True,timeout=5,headers=headers)
log.logger.info('Downloading video: {}'.format(item['title']))
with open('/root/OneDrive/HDvideo/' + item['title'] + '.mp4','wb') as f:
for chunk in r.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
log.logger.info('Downloaded video: {}'.format(item['title']))
except:
log.logger.exception('Something bad happened: ')
finally:
return
class Duplicates_Pipeline(object):
def __init__(self):
self.vkeys_seen = set()
def process_item(self,item,spider):
if item is not None:
if item['vkey'] in self.vkeys_seen:
raise DropItem('Duplicate item found: {}'.format(item))
else:
self.vkeys_seen.add(item['vkey'])
return item
Видео будут сохранены в /root/OneDrive/
, это каталог, смонтированный на моем Vultr VPS с rclone
.Извините за мой английский.Любая помощь будет принята с благодарностью.