Python selenium中的多处理为每个进程打开新窗口

Python selenium中的多处理为每个进程打开新窗口,python,selenium,selenium-webdriver,multiprocessing,bots,Python,Selenium,Selenium Webdriver,Multiprocessing,Bots,我正在开发一个网络机器人,它将在某个网站上完成打字练习。为此,我使用了Selenium和(其常规chromedriver的优化版本,它不会触发反机器人服务,但功能保持不变)。它打开,登录到网站,然后打开当前练习并开始键入。但我需要它在练习完成后停止键入,唯一的方法是继续检查结果是否出现,然后停止type\u text功能。我最初的做法是,在每个字母输入后的type_textfor循环中,我检查var_to_check。但这种方法会大大降低打字速度,因为在每个字母都不断检查var\u to\u c

我正在开发一个网络机器人,它将在某个网站上完成打字练习。为此,我使用了Selenium和(其常规chromedriver的优化版本,它不会触发反机器人服务,但功能保持不变)。它打开,登录到网站,然后打开当前练习并开始键入。但我需要它在练习完成后停止键入,唯一的方法是继续检查结果是否出现,然后停止
type\u text
功能。我最初的做法是,在每个字母输入后的
type_text
for循环中,我检查
var_to_check
。但这种方法会大大降低打字速度,因为在每个字母都不断检查
var\u to\u check
之后。因此,我考虑使用
多处理
,并与
type_text
同时运行检查。我创建了
check\u results
函数,该函数每隔0.1s检查一次
var\u-check
,如果检测到练习结束,则将
shared\u-var
设置为
1
然后
键入\u text
检测到它并停止键入。
出现的问题是,
检查结果
键入文本
过程启动,两个新的Chrome窗口打开,在这两个窗口中,脚本重新启动,它打开网站并尝试让我登录,但失败,因为我已经在第一个窗口中登录。而在原始窗口中,什么也没有发生。不会抛出任何错误

我对
multiprocessing
相当陌生,因此这可能不是最好的方法,例如,使用
multiprocessing.Value
作为进程之间的共享内存,但这是我到目前为止提出的,因此对于处理此问题的任何改进或更好的方法,我们都表示赞赏。但我不明白为什么它要打开两个新窗口,并在其中启动脚本“重新开始”。我需要这两个进程在原来的Chrome窗口上运行。我尝试使用常规的SeleniumWebDriver代替,但没有任何改变

以下是代码,它是从我的原始代码中缩短的,因此可读性更强,但原则保持不变:

来自多处理导入过程的
,值
来自未检测到的chromedriver导入v2作为uc#selenium webdriver附加组件
driver=uc.Chrome()
#使用未检测到的\u chromedriver模块的上下文管理器bcs
与驱动程序:
司机,上车https://some_site.com/')
def登录(驱动程序=驱动程序):
#让我登录网站并打开打字练习
一些代码
def检查结果(共享变量,驱动程序=驱动程序):
#此函数需要与类型_text同时运行
保持检查=1
在不断检查的同时:
var_to_check=driver.find_element_by_xpath(某些_xpath).text
如果变量到检查!='':
使用共享变量get\u lock():
共享变量值=1
保持检查=0
睡眠时间(0.1)
def类型_文本(共享_变量,驱动程序=驱动程序):
text='我需要键入的某些文本'
some\u element=driver.find\u element\u by\u xpath(some\u xpath)
对于文本中的字母:
某些元素。发送密钥(字母)
#我按原来的方式检查,但它减慢了打字速度
#var_to_check=driver.find_element_by_xpath(某些_xpath).text
#如果变量到检查!='':
#中断
#在每封信之后,我都需要检查共享变量的状态
使用共享变量get\u lock():
如果共享变量值==1:
打破
打印('键入结束')
def do_练习():
exc_end=值(“i”,0)
检查变量进程=进程(
目标=检查结果,参数=(exc_结束,)
类型\文本\流程=流程(
target=type\u text,args=(exc\u结束,)
check_var_process.start()
键入\文本\进程。开始()
#此时,它将打开两个新的chrome窗口
check_var_process.join()
键入\u text\u process.join()
results\u of_typing=driver.find\u element\u by\u xpath(某些\u xpath).text
返回键入的结果
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
登录()
结果=做练习()
打印(结果)

首先,当您发布带有
多处理标记的问题时,您还应该添加一个标记,指定您运行的平台。您应该牺牲一个标签,比如
seleniumwebdriver
,这样做。但我怀疑您是在Windows这样的平台下运行的,该平台使用spawn方法创建新进程。这意味着要启动一个新进程,需要创建一个新的空地址空间,加载一个Python解释器,并从顶部重新执行源文件。这就是为什么您必须有
if\uuuuuu name\uuuuu=='\uuuuu main\uuuuu':
控制创建新进程的代码。因为如果不这样做,您将进入一个递归循环,无限地创建新的进程

但这也意味着您在全局范围内拥有的任何代码都将为每个新创建的进程重新执行。而您在全球范围内拥有的是:

driver = uc.Chrome()
# using context manager bcs of undetected_chromedriver module 
with driver:
    driver.get('https://some_site.com/')
    ...
这就是为什么你会有第二个窗口。您需要重新安排一些代码,并显式地将驱动程序传递给您的函数。否则,我没有检查您的逻辑:

如果uuuu name_uuuu=='\uuuuuuu main\uuuuuu':
driver=uc.Chrome()
#使用未检测到的\u chromedriver模块的上下文管理器bcs
与驱动程序:
司机,上车https://some_site.com/')    
登录(驱动程序)
结果=做运动(驾驶员)
打印(结果)
但我怀疑驱动程序是否可以被pickle(标准ChromeDriver不能),这意味着它可以被序列化和反序列化,这需要从主进程的地址空间传递到