gpt4 book ai didi

python-3.x - 如何使Selenium线程运行(每个线程都有自己的驱动程序)

转载 作者:行者123 更新时间:2023-12-03 13:07:44 25 4
gpt4 key购买 nike

我有一个python 3脚本,该脚本需要向多个不同的网站发出数千个请求,并检查其源代码是否通过了一些预定义的规则。

我正在使用selenium发出请求,因为我需要在JS完成执行后获取源代码,但是由于需要检查的URL数量太多,我试图使其同时运行多个线程。每个线程创建和维护的webdriver的实例,使请求。问题是,经过一段时间的所有线程沉默下去,只是停止执行,只留下一个单独的线程做所有的工作。这是我的代码的相关部分:

def get_browser(use_firefox = True):
if use_firefox:
options = FirefoxOptions()
options.headless = True
browser = webdriver.Firefox(options = options)
browser.implicitly_wait(4)
return browser
else:
chrome_options = ChromeOptions()
chrome_options.add_argument("--headless")
browser = webdriver.Chrome(chrome_options=chrome_options)
browser.implicitly_wait(4)
return browser

def start_validations(urls, rules, results, thread_id):
try:
log("thread %s started" % thread_id, thread_id)
browser = get_browser(thread_id % 2 == 1)
while not urls.empty():
url = "http://%s" % urls.get()
try:
log("starting %s" % url, thread_id)
browser.get(url)
time.sleep(0.5)
WebDriverWait(browser, 6).until(selenium_wait_reload(4))
html = browser.page_source
result = check_url(html, rules)

original_domain = url.split("://")[1].split("/")[0].replace("www.","")
tested_domain = browser.current_url.split("://")[1].split("/")[0].replace("www.","")
redirected_url = "" if tested_domain == original_domain else browser.current_url

results.append({"Category":result, "URL":url, "Redirected":redirected_url})
log("finished %s" % url, thread_id)
except Exception as e:
log("couldn't test url %s" % url, thread_id )
log(str(e), thread_id)
results.append({"Category":"Connection Error", "URL":url, "Redirected":""})
browser.quit()
time.sleep(2)
browser = get_browser(thread_id % 2 == 1)
except Exception as e:
log(str(e), thread_id)
finally:
log("closing thread", thread_id)
browser.quit()

def calculate_progress(urls):
progress_folder ="%sprogress/" % WEBROOT
if not os.path.exists(progress_folder):
os.makedirs(progress_folder)

initial_size = urls.qsize()
while not urls.empty():
current_size = urls.qsize()
on_queue = initial_size - current_size
progress = '{0:.0f}'.format((on_queue / initial_size * 100))
for progress_file in os.listdir(progress_folder):
file_path = os.path.join(progress_folder, progress_file)
if os.path.isfile(file_path) and not file_path.endswith(".csv"):
os.unlink(file_path)
os.mknod("%s%s" % (progress_folder, progress))
time.sleep(1)



if __name__ == '__main__':
while True:
try:
log("scraper started")
if os.path.isfile(OUTPUT_FILE):
os.unlink(OUTPUT_FILE)

manager = Manager()

rules = fetch_rules()
urls = manager.Queue()
fetch_urls()
results = manager.list()

jobs = []
p = Process(target=calculate_progress, args=(urls,))
jobs.append(p)
p.start()
for i in range(THREAD_POOL_SIZE):
log("spawning thread with id %s" % i)
p = Process(target=start_validations, args=(urls, rules, results, i))
jobs.append(p)
p.start()
time.sleep(2)
for j in jobs:
j.join()

save_results(results, OUTPUT_FILE)
log("scraper finished")
except Exception as e:
log(str(e))

如您所见,首先我以为我只能拥有一个浏览器实例,所以我尝试至少在paralel中运行firefox和chrome,但这仍然只剩下一个线程来完成所有工作。

有些时候,司机crahsed和线程停止工作,即使它是一个try/catch块里面,所以我开始浏览器每次出现这种情况的一个新实例,但它仍然没有奏效。我还尝试在创建驱动程序的每个实例之间等待几秒钟,但仍然没有结果

这是其中一个日志文件的pastebin:

https://pastebin.com/TsjZdRYf

我注意到的一件奇怪的事是,几乎每次保持运行状态的唯一线程都是最后一个生成的线程(ID为3)。

感谢您的宝贵时间,您将为您提供帮助!

编辑:

[1]以下是完整的代码: https://pastebin.com/fvVPwPVb

[2]自定义 Selenium 的等待条件: https://pastebin.com/Zi7nbNFk

最佳答案

我可以这样骂人吗?我解决了这个问题,我不认为这个答案应该存在于SO上,因为没有其他人会从中受益。问题是我创建的自定义等待条件。此类位于编辑2中添加的pastebin中,但为了方便起见,我还将在此处添加它:

import time
class selenium_wait_reload:
def __init__(self, desired_repeating_sources):
self.desired_repeating_sources = desired_repeating_sources
self.repeated_pages = 0
self.previous_source = None

def __call__(self, driver):
while True:
current_source = driver.page_source
if current_source == self.previous_source:
self.repeated_pages = self.repeated_pages +1
if self.repeated_pages >= self.desired_repeating_sources:
return True
else:
self.previous_source = current_source
self.repeated_pages = 0
time.sleep(0.3)

此类的目的是让 Selenium 等待,因为JS可能正在加载其他DOM。

因此,此类使 Selenium 等待一小段时间并检查代码,再次等待一会儿并再次检查代码。该类重复此操作,直到源代码连续3次相同为止。

问题是,有些页面包含js卡鲁塞尔,因此源代码永远都不相同。我认为在这种情况下,WebDriverWait的第二个参数会使它崩溃并带有timeoutexception。我错了。

关于python-3.x - 如何使Selenium线程运行(每个线程都有自己的驱动程序),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57041431/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com