2016-07-30 8 views
1

私の学士論文では、約40000のウェブサイトからいくつかのデータを取得する必要があります。したがって、私はPythonリクエストを使用していますが、現時点ではサーバからの応答を得るのが実際には遅いです。マルチスレッドのpythonリクエスト

スピードアップして現在のヘッダー設定を維持する方法はありますか?すべてのチュートリアルヘッダーがないところで私は見つけました。ここで

は私のコードが切り取られている:

def parse(url): 
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) ' 
         'Chrome/39.0.2171.95 Safari/537.36'} 
    r = requests.get(url, headers=headers) 

    for line in r.iter_lines(): 
     ... 
+0

おそらく 'aiohttp'ですか? – grooveplex

+0

'マルチプロセッシング 'の使い方は? http://stackoverflow.com/questions/28393617/python-requests-module-multithreading – bsa

+0

@bsaマルチプロセスの必要はなく、新しいプロセスのオーバーヘッドが大きすぎるため、スレッドがioバインドに適しています。 –

答えて

1

grequests(非同期リクエスト)を使用することができますさて、あなたは必要これはI/Oバインドの問題ですのでスレッドを使用してください。組み込みのthreadingライブラリを使用することをお勧めします。 Semaphoreオブジェクトを使用して、現在実行されているスレッド数を調べました。

import time 
import threading 

# Number of parallel threads 
lock = threading.Semaphore(2) 


def parse(url): 
    """ 
    Change to your logic, I just use sleep to mock http request. 
    """ 

    print 'getting info', url 
    sleep(2) 

    # After we done, subtract 1 from the lock 
    lock.release() 


def parse_pool(): 
    # List of all your urls 
    list_of_urls = ['website1', 'website2', 'website3', 'website4'] 

    # List of threads objects I so we can handle them later 
    thread_pool = [] 

    for url in list_of_urls: 
     # Create new thread that calls to your function with a url 
     thread = threading.Thread(target=parse, args=(url,)) 
     thread_pool.append(thread) 
     thread.start() 

     # Add one to our lock, so we will wait if needed. 
     lock.acquire() 

    for thread in thread_pool: 
     thread.join() 

    print 'done' 
+0

ウェブサイトが40000のウェブサイトのリストに複数回含まれている場合はどうなりますか? (もし私が1ページ以上のデータを必要とするなら)どうしたらいいのですか?リクエストの前にランダムな時間だけ待っていますか? – QDA

+0

dictを使う必要があります:キーはウェブサイトのURLになり、値は 'セマフォ'ロックになります。それは少し複雑です。答えが正しければそれを受け入れてください、ありがとう:) @ QDA –

-1

が、私はそれがthreadingmultiprocessのようなmutil-threadを使用することをお勧めだと思う、またはあなたが原因gevent

0

asyncioを使用すると、タスクを同時に実行できます。戻り値asyncio.wait()を使用してURL応答(完了しているものと保留中のもの)をリストし、コルーチンを非同期にコールすることができます。結果は予期しない順序になりますが、より速いアプローチです。

import asyncio 
import functools 


async def parse(url): 
    print('in parse for url {}'.format(url)) 

    info = await #write the logic for fetching the info, it waits for the responses from the urls 

    print('done with url {}'.format(url)) 
    return 'parse {} result from {}'.format(info, url) 


async def main(sites): 
    print('starting main') 
    parses = [ 
     parse(url) 
     for url in sites 
    ] 
    print('waiting for phases to complete') 
    completed, pending = await asyncio.wait(parses) 

    results = [t.result() for t in completed] 
    print('results: {!r}'.format(results)) 


event_loop = asyncio.get_event_loop() 
try: 
    websites = ['site1', 'site2', 'site3'] 
    event_loop.run_until_complete(main(websites)) 
finally: 
    event_loop.close() 
+0

ウェブサイトがその40000ウェブサイトのリストの中に何回もある場合はどうなりますか? (もし私が1ページ以上のデータを必要とするなら)どうしたらいいのですか? – QDA

+0

itertoolsのヘルプから 'repeat'を使うのは助けになりますか? 'itertools import repeat'からです。 'websites.extend( 'sitex'、100)'あなたの必要は何ですか?ページを別々に動的に設定していますか?この繰り返しは、特定の回数だけ特定のウェブサイトを追加する際に役立ちます。 – tworitdash

関連する問題