我正在努力实现如下的目标。
示例代码如下所示。
from splinter import Browser
from multiprocessing import Process, Queue, current_process, freeze_support
#
# Function run by worker processes
#
def worker(input, output):
for func, args in iter(input.get, 'STOP'):
result = calculate(func, args)
output.put(result)
#
# Function used to calculate result
#
def calculate(func, args):
print(args)
result = func(*args)
return '%s says that %s%s = %s' % \
(current_process().name, func.__name__, args, result)
def get_meta_tag_title(browser):
return browser.find_by_xpath('//title')[0]['text']
def get_meta_tag_description(browser):
return browser.find_by_xpath('//description')[0]['text']
#
#
#
def test():
browser = Browser(headless=True)
browser.visit('https://example.com')
NUMBER_OF_PROCESSES = 2
TASKS1 = [(get_meta_tag_title, (browser)), (get_meta_tag_description, (browser))]
# Create queues
task_queue = Queue()
done_queue = Queue()
# Submit tasks
for task in TASKS1:
task_queue.put(task)
# Start worker processes
for i in range(NUMBER_OF_PROCESSES):
Process(target=worker, args=(task_queue, done_queue)).start()
# Get and print results
print('Unordered results:')
for i in range(len(TASKS1)):
print('\t', done_queue.get())
browser.quit()
if __name__ == '__main__':
freeze_support()
test()我的问题是-
TypeError: cannot serialize '_io.BufferedWriter' object中将浏览器实例添加到队列结果中,我应该使用池吗?发布于 2020-07-23 16:43:31
Splinter基于selenium的WebDriver,即非螺纹安全,因此您可能不应该在生产中使用它在单独的线程中。实际上,它可能会起作用,因为您正在执行的操作是只读的。另一个不使用线程的可能原因是,您试图并行化的操作是cpu密集型的,而且在大多数情况下,python线程不会因为GIL而提高性能。
另一方面,多处理确实可以帮助您并行处理cpu密集型工作.但是将浏览器对象传递给每个工作进程(就像您所做的那样)将无法工作,因为浏览器保存打开的文件、套接字,并且有自己的有状态驱动程序实例。这些不能被琐碎的复制和传递到另一个进程。相反,您可以做的是在每个工作人员中创建一个浏览器对象,导航到页面,然后在页面上执行任务。
编辑
要进一步缩短执行时间,可以尝试:
find_by_xpath以外的定位器方法,在遍历整个DOM时,它本身就很慢。requests库获取html内容,使用lxml解析它,而不是使用selenium,因为webdriver可能会造成一些严重的开销。https://stackoverflow.com/questions/62992526
复制相似问题