質問: 概要 --- * スクレイピングはBeautifulSoup4 * async, await がよく分かってない * どうやらurllib.requestのurlopenは同期処理?なのでaiohttpを使うのかな? やりたいこと ------- たとえば、ユニークなドメインのURLが10個あって、すべてのURLから`body`タグ内を引っ張ってきたいとしたとき。 一つのURLに対してのリクエストは一回だけなので、10個のURLを1個ずつ処理するより並列でそれぞれ処理(HTTPリクエスト?)したほうが、取得する順番はどうでもいいですし、処理にかかる時間を相当短縮できるのでは?と思ったわけです。 (全然並列処理について分かってないのでトンチンカンなこと言ってたら叱ってください) ここ2日ほどGoogle先生やQiitaで調べまくってみましたが、色々な書き方や事例がありすぎていまいちよく分かってません・・・ (単に頭が弱いというのが一番かもしれないですが) 拾ってきたコードをデバッグして処理を追ってみたりしましたが、あまり効果はなかったようです。 というわけで、**複数のURLを1つずつではなく、いっぺんに処理がしたい。**というのが私の願望でございます。 教えてください -------- * 超個人的にはPython3.5からの`async`/`await`を使用していきたい(使い方分かってないけど...)です * `async`/`await`の使い方を含めて、上記のような非同期スクレイピングをするにはどういったコードを書くのが良いでしょうか? * とにかく**複数のURLを1つずつではなく、いっぺんに処理がしたい。**ので、なんでも構いません、なにか方法を教えてください。 よろしくお願いします。
回答: 目的は10並列程度の並列処理のようなので非同期処理を手段にする必要性はあまりないと私は思います。非同期処理を使用すればシングルスレッドで効率的な処理が実現できるという側面もありますが、取っ付きやすさの面からスレッドで処理の多重度を上げる方法を提案します。スレッドでの実現方法も色々とありますが`concurrent.futures.ThreadPoolExecutor`が一押しです。以下が`requests`モジュールを使用して複数回ググるサンプルです。 ``` from concurrent.futures import ThreadPoolExecutor import requests urls = [ 'https://google.com/?q=python', 'https://google.com/?q=teratail' ] with ThreadPoolExecutor() as pool: for res in pool.map(requests.get, urls): print(res.status_code, 'url=', res.url) ```