<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何提高爬蟲速度?

          共 2636字,需瀏覽 6分鐘

           ·

          2021-10-28 23:18

          大家好,歡迎來到 Crossin的編程教室 !

          今天在瀏覽知乎時,發(fā)現(xiàn)一個有趣的問題:

          如何優(yōu)化 Python 爬蟲的速度?

          他的問題描述是:

          目前在寫一個 Python 爬蟲,單線程 urllib 感覺過于慢了,達不到數(shù)據(jù)量的要求(十萬級頁面)。求問有哪些可以提高爬取效率的方法?

          這個問題還蠻多人關(guān)注的,但是回答的人卻不多。

          我今天就來嘗試著回答一下這個問題。

          程序提速這個問題其實解決方案就擺在那里,要么通過并發(fā)來提高單位時間內(nèi)處理的工作量,要么從程序本身去找提效點,比如爬取的數(shù)據(jù)用gzip傳輸、提高處理數(shù)據(jù)的速度等。

          我會分別從幾種常見的并發(fā)方法去做同一件事情,從而比較處理效率。

          簡單版本爬蟲

          我們先來一個簡單的爬蟲,看看單線程處理會花費多少時間?

          import?time
          import?requests
          from?datetime?import?datetime


          def?fetch(url):
          ????r?=?requests.get(url)
          ????print(r.text)

          start?=?datetime.now()

          t1?=?time.time()
          for?i?in?range(100):
          ????fetch('http://httpbin.org/get')

          print('requests版爬蟲耗時:',?time.time()?-?t1)

          # requests版爬蟲耗時:54.86306357383728

          我們用一個爬蟲的測試網(wǎng)站,測試爬取100次,用時是54.86秒。

          多線程版本爬蟲

          下面我們將上面的程序改為多線程版本:

          import?threading
          import?time
          import?requests


          def?fetch():
          ????r?=?requests.get('http://httpbin.org/get')
          ????print(r.text)

          t1?=?time.time()

          t_list?=?[]
          for?i?in?range(100):
          ????t?=?threading.Thread(target=fetch,?args=())
          ????t_list.append(t)
          ????t.start()

          for?t?in?t_list:
          ????t.join()

          print("多線程版爬蟲耗時:",?time.time()?-?t1)

          #?多線程版爬蟲耗時:0.8038511276245117

          我們可以看到,用上多線程之后,速度提高了68倍。其實用這種方式的話,由于我們并發(fā)操作,所以跑100次跟跑一次的時間基本是一致的。這只是一個簡單的例子,實際情況中我們不可能無限制地增加線程數(shù)。

          多進程版本爬蟲

          除了多線程之外,我們還可以使用多進程來提高爬蟲速度:

          import?requests
          import?time
          import?multiprocessing
          from?multiprocessing?import?Pool

          MAX_WORKER_NUM?=?multiprocessing.cpu_count()

          def?fetch():
          ????r?=?requests.get('http://httpbin.org/get')
          ????print(r.text)

          if?__name__?==?'__main__':
          ????t1?=?time.time()
          ????p?=?Pool(MAX_WORKER_NUM)
          ????for?i?in?range(100):
          ????????p.apply_async(fetch,?args=())
          ????p.close()
          ????p.join()

          ????print('多進程爬蟲耗時:',?time.time()?-?t1)

          多進程爬蟲耗時:?7.9846765995025635

          我們可以看到多進程處理的時間是多線程的10倍,比單線程版本快7倍。

          協(xié)程版本爬蟲

          我們將程序改為使用 aiohttp 來實現(xiàn),看看效率如何:

          import?aiohttp
          import?asyncio
          import?time


          async?def?fetch(client):
          ????async?with?client.get('http://httpbin.org/get')?as?resp:
          ????????assert?resp.status?==?200
          ????????return?await?resp.text()


          async?def?main():
          ????async?with?aiohttp.ClientSession()?as?client:
          ????????html?=?await?fetch(client)
          ????????print(html)

          loop?=?asyncio.get_event_loop()

          tasks?=?[]
          for?i?in?range(100):
          ????task?=?loop.create_task(main())
          ????tasks.append(task)

          t1?=?time.time()

          loop.run_until_complete(main())

          print("aiohttp版爬蟲耗時:",?time.time()?-?t1)

          aiohttp版爬蟲耗時:?0.6133313179016113

          我們可以看到使用這種方式實現(xiàn),比單線程版本快90倍,比多線程還快。

          結(jié)論

          通過上面的程序?qū)Ρ龋覀兛梢钥吹剑瑢τ诙嗳蝿?wù)爬蟲來說,多線程、多進程、協(xié)程這幾種方式處理效率的排序為:aiohttp > 多線程 > 多進程。因此,對于簡單的爬蟲任務(wù),如果想要提高效率,可以考慮使用協(xié)程。但是同時也要注意,這里只是簡單的示例,實際運用中,我們一般會用線程池、進程池、協(xié)程池去操作。

          這就是問題的答案了嗎?

          對于一個嚴謹?shù)某绦騿T來說,當(dāng)然不是,實際上還有一些優(yōu)化的庫,例如grequests,可以從請求上解決并發(fā)問題。實際的處理過程中,肯定還有其他的優(yōu)化點,這里只是從最常見的幾種并發(fā)方式去比較而已,應(yīng)付簡單爬蟲還是可以的,其他的方式歡迎大家在評論區(qū)留言探討。

          獲取文中相關(guān)代碼,請在公眾號 Crossin的編程教室 回復(fù)關(guān)鍵字:?加速

          如果文章對你有幫助,歡迎轉(zhuǎn)發(fā)/點贊/收藏~

          作者:閑歡

          來源:Python 技術(shù)「ID: pythonall」



          _往期文章推薦_

          爬蟲必備工具,掌握它就解決了一半的問題




          如需了解付費精品課程教學(xué)答疑服務(wù)請在Crossin的編程教室內(nèi)回復(fù): 666

          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  熟女无码| 亚洲在线观看免费视频 | 高清无码视频免费在线观看 | 91视频啊啊啊 | 天堂五月丁香 |