Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/73.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 如何并行运行Selenium scrapy_Python_Selenium_Web Scraping_Scrapy_Multiprocessing - Fatal编程技术网

Python 如何并行运行Selenium scrapy

Python 如何并行运行Selenium scrapy,python,selenium,web-scraping,scrapy,multiprocessing,Python,Selenium,Web Scraping,Scrapy,Multiprocessing,我正在尝试使用scrapy和selenium来创建一个javascript网站。我使用seleniumRequest和chrome驱动程序打开javascript网站,并使用scrapy从当前页面中删除指向不同列表的所有链接,并将它们存储在列表中(这是迄今为止最好的方法,因为尝试使用seleniumRequest跟踪链接并回拨到解析新页面函数会导致很多错误)。然后,我循环浏览URL列表,在selenium驱动程序中打开它们,并从页面中获取信息。到目前为止,这个网站每分钟只剩下16页,考虑到这个网

我正在尝试使用scrapy和selenium来创建一个javascript网站。我使用seleniumRequest和chrome驱动程序打开javascript网站,并使用scrapy从当前页面中删除指向不同列表的所有链接,并将它们存储在列表中(这是迄今为止最好的方法,因为尝试使用seleniumRequest跟踪链接并回拨到解析新页面函数会导致很多错误)。然后,我循环浏览URL列表,在selenium驱动程序中打开它们,并从页面中获取信息。到目前为止,这个网站每分钟只剩下16页,考虑到这个网站上的列表数量,这并不理想。理想情况下,我会让selenium驱动程序并行打开链接,如以下实现:

然而,我不知道如何在我的selenium scrapy代码中实现并行处理`

    import scrapy
    import time
    from scrapy.selector import Selector
    from scrapy_selenium import SeleniumRequest
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.support.ui import Select
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC

class MarketPagSpider(scrapy.Spider):
    name = 'marketPagination'
def start_requests(self):
    yield SeleniumRequest(
        url="https://www.cryptoslam.io/nba-top-shot/marketplace",
        wait_time=5,
        wait_until=EC.presence_of_element_located((By.XPATH, '//SELECT[@name="table_length"]')),
        callback=self.parse
    )

responses = []

def parse(self, response):
    # initialize driver
    driver = response.meta['driver']
    driver.set_window_size(1920,1080)

    time.sleep(1)
    WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, "(//th[@class='nowrap sorting'])[1]"))
    )

    rows = response_obj.xpath("//tbody/tr[@role='row']")
    for row in rows:
        link = row.xpath(".//td[4]/a/@href").get()
        absolute_url = response.urljoin(link)

        self.responses.append(absolute_url)

    for resp in self.responses:
        driver.get(resp)
        html = driver.page_source 
        response_obj = Selector(text=html)

        yield {
        'name': response_obj.xpath("//div[@class='ibox-content animated fadeIn fetchable-content js-attributes-wrapper']/h4[4]/span/a/text()").get(),
        'price': response_obj.xpath("//span[@class='js-auction-current-price']/text()").get()
        
        }
我知道scrapy splash可以处理多个处理过程,但我试图清理的网站无法在splash中打开(至少我不这么认为)

此外,我还删除了用于分页的代码行,以保持代码简洁


我对这一点非常陌生,并愿意接受关于使用selenium进行多处理的任何建议和解决方案。

以下示例程序创建了一个仅包含2个线程的线程池,用于演示,然后删除4个URL以获取其标题:

从multiprocessing.pool导入线程池
从bs4导入BeautifulSoup
从selenium导入webdriver
导入线程
导入gc
类驱动程序:
定义初始化(自):
options=webdriver.ChromeOptions()
选项。添加参数(“--headless”)
#禁止记录:
选项。添加实验选项('ExcludeSwitchs',['enable-logging'])
self.driver=webdriver.Chrome(选项=选项)
打印('驱动程序刚刚创建')
定义(自我):
self.driver.quit()
打印('驱动程序已终止')
threadLocal=threading.local()
def create_驱动程序():
驱动程序=getattr(threadLocal,'the驱动程序',无)
如果_驱动程序为无:
驱动程序=驱动程序()
setattr(threadLocal,_驱动程序,_驱动程序)
返回驱动程序
def get_标题(url):
驱动程序=创建驱动程序()
获取驱动程序(url)
source=BeautifulSoup(driver.page_source,“lxml”)
标题=来源。选择一个(“标题”)。文本
打印(f“{url}:{title}”)
#出于演示目的,我们的池中只有2个线程:
使用线程池(2)作为池:
URL=[
'https://www.google.com',
'https://www.microsoft.com',
'https://www.ibm.com',
'https://www.yahoo.com'
]
map(获取标题、URL)
#必须在对池显式或隐式调用terminate之前完成:
del threadLocal
gc.collect()
#在with块的出口处调用pool.terminate()
印刷品:

The driver was just created.
The driver was just created.
https://www.google.com: 'Google'
https://www.microsoft.com: 'Microsoft - Official Home Page'
https://www.ibm.com: 'IBM - United States'
https://www.yahoo.com: 'Yahoo'
The driver has terminated.
The driver has terminated.

发布多处理代码后,它会像往常一样工作,但每个“线程/进程”都应该使用自己的线程/进程driver@Wonka我真的不知道如何实现这一点。一般来说,我对多处理库非常不熟悉,我为基本技术和公认的答案以及我的(Booboo)道歉答案,确保驱动程序在您完成时终止。接受的答案是一种技术,即每个线程使用一个驱动程序,而不是每个URL使用一个驱动程序。换句话说,它重用驱动程序,就像您在非线程代码中对所有URL重用驱动程序一样。@Booboo嘿,谢谢您的答案!我设法让selenium进入multipro我喜欢你的解决方案。但是,在脚本完成后,我似乎无法删除驱动程序,即使我将del threadlocal放在了末尾。实际上,我最终得到了以下错误:NameError:name'threadlocal'未定义在接受的答案是声明
threadlocal=threading.local()
。我没有复制到我的答案中所需的那一行,而是假设它已被理解。我现在已经更新了答案,以明确声明。