2 回答

TA貢獻1810條經驗 獲得超4個贊
我拿了你的代碼,稍微修改了一下以適應我的測試環境,這里是執行結果:
代碼塊:
multiprocess.py:
import time
from multiprocessing import Pool
from multiprocessingPool.scrape import run_scrape
if __name__ == '__main__':
start_time = time.time()
links = ["https://selenium.dev/downloads/", "https://selenium.dev/documentation/en/"]
pool = Pool(2)
results = pool.map(run_scrape, links)
pool.close()
print("Total Time Processed: "+"--- %s seconds ---" % (time.time() - start_time))
scrape.py:
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
def run_scrape(link):
chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument("--headless")
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument("--lang=en")
chrome_options.add_argument("--start-maximized")
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")
chrome_options.binary_location=r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
browser = webdriver.Chrome(executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe', options=chrome_options)
browser.get(link)
try:
print(browser.title)
except (NoSuchElementException, TimeoutException):
print("Error")
browser.quit()
控制臺輸出:
Downloads
The Selenium Browser Automation Project :: Documentation for Selenium
Total Time Processed: --- 10.248600006103516 seconds ---
結論
很明顯,您的程序在邏輯上是完美無缺的。
這個用例
正如您在幾個小時的抓取后提到的這個錯誤表面,我懷疑這是因為WebDriver 不是線程安全的。話雖如此,如果您可以序列化對底層驅動程序實例的訪問,則可以在多個線程中共享一個引用。這是不可取的。但是您總是可以為每個線程實例化一個WebDriver實例。
理想情況下,線程安全問題不在您的代碼中,而在實際的瀏覽器綁定中。他們都假設一次只會有一個命令(例如,像一個真實的用戶)。但另一方面,您始終可以為每個線程實例化一個WebDriver實例,該實例將啟動多個瀏覽選項卡/窗口。到目前為止,您的程序似乎很完美。
現在,不同的線程可以在同一個Webdriver上運行,但是測試的結果不會是你所期望的。背后的原因是,當您使用多線程在不同的選項卡/窗口上運行不同的測試時,需要一點線程安全編碼,否則您將執行的操作就像click()或send_keys()將轉到當前打開的選項卡/窗口一樣無論您希望運行的線程如何,都將成為焦點。這實質上意味著所有測試將在具有焦點但不在預期的選項卡/窗口上的同一選項卡/窗口上同時運行。

TA貢獻1876條經驗 獲得超6個贊
現在我使用這個線程模塊為每個線程實例化一個 Webdriver
import threading
threadLocal = threading.local()
def get_driver():
browser = getattr(threadLocal, 'browser', None)
if browser is None:
chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument("--headless")
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument("--lang=en")
chrome_options.add_argument("--start-maximized")
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")
chrome_options.binary_location = "/usr/bin/google-chrome"
browser = webdriver.Chrome(executable_path=r'/usr/local/bin/chromedriver', options=chrome_options)
setattr(threadLocal, 'browser', browser)
return browser
它確實幫助我比一次執行一個驅動程序更快。
添加回答
舉報