Python Scrapy:在另一个线程中下载base64映像
我有一个像下面这样的爬行器,它从API获取信息,除此之外,我想下载base64格式的产品图像,但是爬行过程变得如此缓慢,我如何用另一种方式来完成它,例如,使用线程Python Scrapy:在另一个线程中下载base64映像,python,multithreading,scrapy,multiprocessing,Python,Multithreading,Scrapy,Multiprocessing,我有一个像下面这样的爬行器,它从API获取信息,除此之外,我想下载base64格式的产品图像,但是爬行过程变得如此缓慢,我如何用另一种方式来完成它,例如,使用线程 class ExampleMobilePhoneSpider(Spider): name = "example" allowed_domains = ["www.example.com", "example.com"] start_urls = ( 'https://search.example
class ExampleMobilePhoneSpider(Spider):
name = "example"
allowed_domains = ["www.example.com", "example.com"]
start_urls = (
'https://search.example.com/api/search/?category=c11&pageno=0',
)
custom_settings = {
"ITEM_PIPELINES": {
'crawler_bot.pipelines.ExampleElectronicDevicePipeline': 100,
}
}
def parse_item(self, response):
js = json.loads(response.body.decode('utf-8'))
hits = js['hits']['hits']
for counter, hit in enumerate(hits):
l = ItemLoader(item=ProductDetail(), response=response)
m = hits[counter]['_source']
# print(json.dumps(m, indent=4, sort_keys=True))
l.add_value('enTitle', m['EnTitle'])
l.add_value('faTitle', m['FaTitle'])
l.add_value('minPrice', {"value": m['MinPrice'], "updateDate": datetime.datetime.now()})
l.add_value('price', {"value": m['MinPriceList'], "updateDate": datetime.datetime.now()})
l.add_value('maxPrice', {"value": m['MaxPrice'], "updateDate": datetime.datetime.now()})
l.add_value('isActive', m['IsActive'])
l.add_value('isEspecialOffer', m['IsSpecialOffer'])
l.add_value('productCategories', m['ProductCategories'].split())
l.add_value('imagePath', m['ImagePath'])
l.add_value('hasVideo', m['HasVideo'])
l.add_value('productColorList', m['ProductColorList'])
l.add_value('localID', m['Id'])
l.add_value('url', response.url)
l.add_value('project', "example")
l.add_value('subject', ["electronic_device", "mobile_phone", "mobile"])
l.add_value('spider', self.name)
l.add_value('server', socket.gethostname())
l.add_value('date', datetime.datetime.now())
l.add_value('collection', "electronic_device")
file_path = "https://file.example.com/example/"
l.add_value('images', image2base64.get_as_base64(file_path + m['ImagePath']))
yield l.load_item()
def parse(self, response):
base_url_mobile = 'https://search.example.com/api/search/?category=c11&pageno='
urls = [base_url_mobile + str(n) for n in range(2)]
for url in urls:
yield Request(urljoin(response.url, url), callback=self.parse_item)
有几种方法,下面的示例使用一个队列和一组工作线程来执行请求/响应处理和图像下载
from threading import Thread
from Queue import Queue
class ExampleMobilePhoneSpider(Spider):
def __init__(self, num_workers=10, q_size=100):
self.in_q = Queue(q_size)
self.worker_threads = [Thread(
target=self.worker, args=(self.in_q,))
for _ in range(num_workers)]
for _thread in self.worker_threads:
_thread.daemon = True
_thread.start()
def worker(self):
while True:
_url = self.in_q.get()
Request(_url, callback=self.parse_item)
def parse(self, response):
base_url_mobile = 'https://search.example.com/api/search/?category=c11&pageno='
urls = [base_url_mobile + str(n) for n in range(2)]
for url in urls:
self.in_q.add(urljoin(response.url, url))
把你自己的线和刮痧混合通常是个坏主意。也没有必要,Scrapy使用Twisted的Reactor模式实现并发,如果硬件足够大,它可以同时处理1000个请求。。。并且settings.py中的设置允许它 因为我看不到您的图像管道实现,也看不到您的settings.py这有点猜测,但您应该尝试以下两种方法: 增加每个\u域的并发\u请求和并发\u请求设置,否则您的spider将同时只下载有限数量的页面和文件 检查映像管道是否存在cpu密集型处理或阻塞行为
你测试代码了吗?除了将线程与scrapy混合(这不是一个好主意)之外,您的代码看起来会启动一些线程来创建大量永远不会执行的scrapy请求对象……OP代码示例不完整,缩进不好,因此不可能基于它测试任何代码。你有什么具体问题吗?到目前为止你试过什么?有很多方法可以做到这一点,可以很容易地使线程目标函数成为图像下载,而不做任何解析/剪贴使用。这取决于你想要什么。无论哪种方式,您都需要显示一些工作代码,并在此基础上提出问题。您是否通过实现下载程序管道进行了尝试?使用管道,我只是将数据存储在MongoDB和Elasticsearch中