2017-12-12 7 views
0

URLのプールをスクラップするには、私はjoblibでセレンを並列処理しています。この文脈で、私は2つの課題に直面しています:並列処理中にセレニウムドライバインスタンスを再利用するには?

  • 挑戦1は、このプロセスをスピードアップすることです。現時点では、私のコードは、すべてのURL(理想的にはすべてのプロセスの1つになる)のドライバインスタンスを開き、閉じます。
  • 挑戦2はCPU集約的なwhileループを取り除くことですが、空の結果にはcontinue私の理解では、反復の間でドライバインスタンスを再利用するためには、# Set up driver -lineをする必要があるということである

    URL_list = [URL1, URL2, URL3, ..., URL100000]     # List of URLs to be scraped 
    
    def scrape(URL): 
        while True:             # Loop needed to use continue 
          try:            # Try scraping 
          driver = webdriver.Firefox(executable_path=path) # Set up driver 
          website = driver.get(URL)      # Get URL 
          results = do_something(website)     # Get results from URL content             
          driver.close()         # Close worker 
          if len(results) == 0:       # If do_something() failed:                 
           continue          # THEN Worker to skip URL       
          else:           # If do_something() worked: 
           safe_results("results.csv")     # THEN Save results    
           break           # Go to next worker/URL 
          except Exception as e:        # If something weird happens: 
           save_exception(URL, e)      # THEN Save error message 
           break           # Go to next worker/URL 
    
    Parallel(n_jobs = 40)(delayed(scrape)(URL) for URL in URL_list))) # Run in 40 processes 
    

    :擬似コード

(私は、これが最も可能性の高い間違っていることを知っています)外に置いたscrape(URL) 。しかし、scrape(URL)以外のものは、ジョブライブラリのParallel(n_jobs = 40)には届きません。これは、trueではないjoblibを使用してスクラップしている間にドライバインスタンスを再利用することができないことを意味します。

1:上記の例の並列処理中にドライバインスタンスを再利用するにはどうすればよいですか?

Q2:上記の例の機能を維持しながらwhileループを取り除くにはどうすればよいですか?

注:フラッシュおよび画像負荷はfirefox_profileで無効になって

答えて

1

1)最初に、ドライバの束を作成する必要があり(コード図示せず)が各プロセスのための1つを。そして、作業者にインスタンスを渡します。ドライバをPrallelオブジェクトに渡す方法はわかりませんが、threading.current_thread().nameキーを使用してドライバを識別できます。これを行うには、backend="threading"を使用してください。今は各スレッドに独自のドライバがあります。

2)ループは一切必要ありません。すべてのあなたのURL ITER並列オブジェクト自身(私は本当にループを使用するためにあなたの意図をunderstend願っています)

import threading 
from joblib import Parallel, delayed 
from selenium import webdriver 

def scrape(URL): 
    try: 
     driver = drivers[threading.current_thread().name] 
    except KeyError: 
     drivers[threading.current_thread().name] = webdriver.Firefox() 
     driver = drivers[threading.current_thread().name] 
    driver.get(URL) 
    results = do_something(driver) 
    if results: 
     safe_results("results.csv") 

drivers = {} 
Parallel(n_jobs=-1, backend="threading")(delayed(scrape)(URL) for URL in URL_list) 
for driver in drivers.values(): 
    driver.quit() 

しかし、私は本当にあなたがCPUを持っている以上のことをn_job使用して利益を得るとは思いません。だからn_jobs=-1が最高です(もちろん私は間違っているかもしれません)。

+0

私はそれを試してみましたが、何かがメモリリークを引き起こします。私はこの問題を解決するとすぐにあなたに戻ってきます。 – sudonym

+0

@sudonym、リークを作成していましたか? – suit

+0

リークはphantomJS(Firefoxの代わりに使用しています)が原因です - 'load_images = no argument'はphantomJSインスタンスが再利用されたときにこれを引き起こすことが知られています – sudonym

関連する問題