Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Scrapy:在另一个线程中下载base64映像_Python_Multithreading_Scrapy_Multiprocessing - Fatal编程技术网

Python Scrapy:在另一个线程中下载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

我有一个像下面这样的爬行器,它从API获取信息,除此之外,我想下载base64格式的产品图像,但是爬行过程变得如此缓慢,我如何用另一种方式来完成它,例如,使用线程

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中