如何使用selenium同时打开多个实例Firefox而不清除缓存和cookie

时间:2016-08-07 07:04:04

标签: python selenium cookies selenium-grid

我有一个代码从Facebook UID抓取好友列表。它起作用但是需要很长时间才能完成整个列表。所以,我希望通过使用多处理和Selenium Grid加快速度。以下是我使用的方法:

  1. 使用帐户登录Facebook
  2. 打开5个具有相同缓存和cookie的Firefox实例(因此我不需要再次登录)
  3. 同时从5个不同的UID抓取好友列表。 1个实例/ 1个UID
  4. 这是我的代码,但它不起作用

    import multiprocessing
    from selenium.common.exceptions import TimeoutException
    from bs4 import BeautifulSoup
    from selenium import webdriver
    
    def friend_uid_list(uid, driver):
        driver.get('https://www.facebook.com/' + uid + '/friends')
        //scrape friend list
        target.close()
    
    def g(arg):
        return friend_uid_list(*arg)
    
    if __name__ == '__main__':
    
        driver = webdriver.Firefox()
        driver.get("https://www.facebook.com/")
        driver.find_element_by_css_selector("#email").send_keys("email@gmail.com")
        driver.find_element_by_css_selector("#pass").send_keys("password")
        driver.find_element_by_css_selector("#u_0_m").click()
    
        pool = multiprocessing.Pool(5)
        pool.map(g, [(100004159542140,driver),(100004159542140,driver),(100004159542140,driver)])
    

    那么,您能告诉我如何使用Selenium Grid同时使用多个实例吗?我搜索了很多,但不知道如何将其实现到我的代码中。谢谢:))

1 个答案:

答案 0 :(得分:2)

这是另一种不使用硒网格的方法。

此方法打开5个firefox实例,以及每个实例上的3个窗口。 Cookie将从主实例中复制。

from pyvirtualdisplay import Display
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import multiprocessing
display = Display(visible=0, size=(800, 600))
display.start()
d = webdriver.Firefox()

def friend_uid_list(uid, driver):
    values = []
    for handle in driver.window_handles:
        driver.switch_to_window(handle)
        # driver.wait_for_element() etc etc
        values.append(driver.find_element_by_id('#something'))
        # scrape elements
    return values

def g(arg):
    return friend_uid_list(*arg)

启动实例并登录:

d = webdriver.Firefox()
d.get("https://www.facebook.com/")
d.find_element_by_css_selector("#email").send_keys("email@gmail.com")
d.find_element_by_css_selector("#pass").send_keys("password")
d.find_element_by_css_selector("#loginbutton").click()

启动多个实例:

drivers = [webdriver.Firefox(), webdriver.Firefox(), webdriver.Firefox(), webdriver.Firefox()]

复制localStorage

localstorage_kv = d.execute_script("var obj={};for (var i=0,len=localStorage.length;i<len;++i){obj[localStorage.key(i)]=localStorage.getItem(localStorage.key(i));};return obj")

复制Cookie并localStorage

for e in drivers:
    e.get("https://www.facebook.com/")
    for x in d.get_cookies():
        e.add_cookie(x)
    for k, v in localstorage_kv.items():
        e.execute_script('localStorage.setItem("{}", {})'.format(k,v))
    e.refresh() # should be logged in now

将初始驱动程序添加回驱动程序数组:

drivers.append(d)

然后遍历uids:

uids = [100004159542140, 100004159542140, 100004159542140, 100004159542140, 100004159542140, 100004159542140]
pool = multiprocessing.Pool(5)

while uids:
    for driver in drivers:
        if len(driver.window_handles) == 1:
            driver.execute_script('window.open("https://www.facebook.com/' + uids.pop() + '/friends")')            
            driver.execute_script('window.open("https://www.facebook.com/' + uids.pop() + '/friends")')            
        else:
            for handle in driver.window_handles:
                handle.get("https://www.facebook.com/" + uids.pop() + "/friends")
    return_values = pool.map(g, drivers)
    import pdb;pdb.set_trace()

如果你真的想在selenium网格上的节点之间共享cookie,请看:

这大致意味着挑选localStoragecookies并将其转移到每个节点,然后从那里读取cookie到每个节点上的每个实例。