<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>

          Python爬蟲實(shí)戰(zhàn):單線程、多線程和協(xié)程性能對比

          共 9309字,需瀏覽 19分鐘

           ·

          2021-01-29 11:15

          一、前言

          今天我要給大家分享的是如何爬取中農(nóng)網(wǎng)產(chǎn)品報(bào)價(jià)數(shù)據(jù),并分別用普通的單線程、多線程和協(xié)程來爬取,從而對比單線程、多線程和協(xié)程在網(wǎng)絡(luò)爬蟲中的性能。
          目標(biāo)URL:https://www.zhongnongwang.com/quote/product-htm-page-1.html
          爬取產(chǎn)品品名、最新報(bào)價(jià)、單位、報(bào)價(jià)數(shù)、報(bào)價(jià)時間等信息,保存到本地Excel。

          二、爬取測試

          翻頁查看 URL 變化規(guī)律:
          https://www.zhongnongwang.com/quote/product-htm-page-1.html
          https://www.zhongnongwang.com/quote/product-htm-page-2.html
          https://www.zhongnongwang.com/quote/product-htm-page-3.html
          https://www.zhongnongwang.com/quote/product-htm-page-4.html
          https://www.zhongnongwang.com/quote/product-htm-page-5.html
          https://www.zhongnongwang.com/quote/product-htm-page-6.html
          檢查網(wǎng)頁,可以發(fā)現(xiàn)網(wǎng)頁結(jié)構(gòu)簡單,容易解析和提取數(shù)據(jù)。
          思路:每一條產(chǎn)品報(bào)價(jià)信息在 class 為 tb 的 table 標(biāo)簽下的 tbody 下的 tr 標(biāo)簽里,獲取到所有 tr 標(biāo)簽的內(nèi)容,然后遍歷,從中提取出每一個產(chǎn)品品名、最新報(bào)價(jià)、單位、報(bào)價(jià)數(shù)、報(bào)價(jià)時間等信息。
          #?-*-?coding:?UTF-8?-*-
          """
          @File ???:demo.py
          @Author ?:葉庭云
          @CSDN ???:https://yetingyun.blog.csdn.net/
          """

          import?requests
          import?logging
          from?fake_useragent?import?UserAgent
          from?lxml?import?etree


          #?日志輸出的基本配置
          logging.basicConfig(level=logging.INFO,?format='%(asctime)s?-?%(levelname)s:?%(message)s')
          #?隨機(jī)產(chǎn)生請求頭
          ua?=?UserAgent(verify_ssl=False,?path='fake_useragent.json')
          url?=?'https://www.zhongnongwang.com/quote/product-htm-page-1.html'
          #?偽裝請求頭
          headers?=?{
          ????"Accept-Encoding":?"gzip",??#?使用gzip壓縮傳輸數(shù)據(jù)讓訪問更快
          ????"User-Agent":?ua.random
          }
          #?發(fā)送請求??獲取響應(yīng)
          rep?=?requests.get(url,?headers=headers)
          print(rep.status_code)????#?200
          #?Xpath定位提取數(shù)據(jù)
          html?=?etree.HTML(rep.text)
          items?=?html.xpath('/html/body/div[10]/table/tr[@align="center"]')
          logging.info(f'該頁有多少條信息:{len(items)}')??#?一頁有20條信息
          #?遍歷提取出數(shù)據(jù)
          for?item?in?items:
          ????name?=?''.join(item.xpath('.//td[1]/a/text()'))??#?品名
          ????price?=?''.join(item.xpath('.//td[3]/text()'))???#?最新報(bào)價(jià)
          ????unit?=?''.join(item.xpath('.//td[4]/text()'))????#?單位
          ????nums?=?''.join(item.xpath('.//td[5]/text()'))????#?報(bào)價(jià)數(shù)
          ????time_?=?''.join(item.xpath('.//td[6]/text()'))???#?報(bào)價(jià)時間
          ????logging.info([name,?price,?unit,?nums,?time_])
          運(yùn)行結(jié)果如下:
          可以成功爬取到數(shù)據(jù),接下來分別用普通的單線程、多線程和協(xié)程來爬取 50 頁的數(shù)據(jù)、保存到Excel。

          三、單線程爬蟲

          #?-*-?coding:?UTF-8?-*-
          """
          @File ???:單線程.py
          @Author ?:葉庭云
          @CSDN ???:https://yetingyun.blog.csdn.net/
          """

          import?requests
          import?logging
          from?fake_useragent?import?UserAgent
          from?lxml?import?etree
          import?openpyxl
          from?datetime?import?datetime

          #?日志輸出的基本配置
          logging.basicConfig(level=logging.INFO,?format='%(asctime)s?-?%(levelname)s:?%(message)s')
          #?隨機(jī)產(chǎn)生請求頭
          ua?=?UserAgent(verify_ssl=False,?path='fake_useragent.json')
          wb?=?openpyxl.Workbook()
          sheet?=?wb.active
          sheet.append(['品名',?'最新報(bào)價(jià)',?'單位',?'報(bào)價(jià)數(shù)',?'報(bào)價(jià)時間'])
          start?=?datetime.now()

          for?page?in?range(1,?51):
          ????#?構(gòu)造URL
          ????url?=?f'https://www.zhongnongwang.com/quote/product-htm-page-{page}.html'
          ????#?偽裝請求頭
          ????headers?=?{
          ????????"Accept-Encoding":?"gzip",??#?使用gzip壓縮傳輸數(shù)據(jù)讓訪問更快
          ????????"User-Agent":?ua.random
          ????}
          ????#?發(fā)送請求??獲取響應(yīng)
          ????rep?=?requests.get(url,?headers=headers)
          ????#?print(rep.status_code)
          ????#?Xpath定位提取數(shù)據(jù)
          ????html?=?etree.HTML(rep.text)
          ????items?=?html.xpath('/html/body/div[10]/table/tr[@align="center"]')
          ????logging.info(f'該頁有多少條信息:{len(items)}')??#?一頁有20條信息
          ????#?遍歷提取出數(shù)據(jù)
          ????for?item?in?items:
          ????????name?=?''.join(item.xpath('.//td[1]/a/text()'))??#?品名
          ????????price?=?''.join(item.xpath('.//td[3]/text()'))???#?最新報(bào)價(jià)
          ????????unit?=?''.join(item.xpath('.//td[4]/text()'))????#?單位
          ????????nums?=?''.join(item.xpath('.//td[5]/text()'))????#?報(bào)價(jià)數(shù)
          ????????time_?=?''.join(item.xpath('.//td[6]/text()'))???#?報(bào)價(jià)時間
          ????????sheet.append([name,?price,?unit,?nums,?time_])
          ????????logging.info([name,?price,?unit,?nums,?time_])


          wb.save(filename='data1.xlsx')
          delta?=?(datetime.now()?-?start).total_seconds()
          logging.info(f'用時:{delta}s')
          運(yùn)行結(jié)果如下:

          單線程爬蟲必須上一個頁面爬取完成才能繼續(xù)爬取,還可能受當(dāng)時網(wǎng)絡(luò)狀態(tài)影響,用時48.528703s,才將數(shù)據(jù)爬取完,速度比較慢。

          四、多線程爬蟲

          #?-*-?coding:?UTF-8?-*-
          """
          @File ???:多線程.py
          @Author ?:葉庭云
          @CSDN ???:https://yetingyun.blog.csdn.net/
          """

          import?requests
          import?logging
          from?fake_useragent?import?UserAgent
          from?lxml?import?etree
          import?openpyxl
          from?concurrent.futures?import?ThreadPoolExecutor,?wait,?ALL_COMPLETED
          from?datetime?import?datetime

          #?日志輸出的基本配置
          logging.basicConfig(level=logging.INFO,?format='%(asctime)s?-?%(levelname)s:?%(message)s')
          #?隨機(jī)產(chǎn)生請求頭
          ua?=?UserAgent(verify_ssl=False,?path='fake_useragent.json')
          wb?=?openpyxl.Workbook()
          sheet?=?wb.active
          sheet.append(['品名',?'最新報(bào)價(jià)',?'單位',?'報(bào)價(jià)數(shù)',?'報(bào)價(jià)時間'])
          start?=?datetime.now()


          def?get_data(page):
          ????#?構(gòu)造URL
          ????url?=?f'https://www.zhongnongwang.com/quote/product-htm-page-{page}.html'
          ????#?偽裝請求頭
          ????headers?=?{
          ????????"Accept-Encoding":?"gzip",????#?使用gzip壓縮傳輸數(shù)據(jù)讓訪問更快
          ????????"User-Agent":?ua.random
          ????}
          ????#?發(fā)送請求??獲取響應(yīng)
          ????rep?=?requests.get(url,?headers=headers)
          ????#?print(rep.status_code)
          ????#?Xpath定位提取數(shù)據(jù)
          ????html?=?etree.HTML(rep.text)
          ????items?=?html.xpath('/html/body/div[10]/table/tr[@align="center"]')
          ????logging.info(f'該頁有多少條信息:{len(items)}')??#?一頁有20條信息
          ????#?遍歷提取出數(shù)據(jù)
          ????for?item?in?items:
          ????????name?=?''.join(item.xpath('.//td[1]/a/text()'))???#?品名
          ????????price?=?''.join(item.xpath('.//td[3]/text()'))????#?最新報(bào)價(jià)
          ????????unit?=?''.join(item.xpath('.//td[4]/text()'))?????#?單位
          ????????nums?=?''.join(item.xpath('.//td[5]/text()'))?????#?報(bào)價(jià)數(shù)
          ????????time_?=?''.join(item.xpath('.//td[6]/text()'))????#?報(bào)價(jià)時間
          ????????sheet.append([name,?price,?unit,?nums,?time_])
          ????????logging.info([name,?price,?unit,?nums,?time_])


          def?run():
          ????#?爬取1-50頁
          ????with?ThreadPoolExecutor(max_workers=6)?as?executor:
          ????????future_tasks?=?[executor.submit(get_data,?i)?for?i?in?range(1,?51)]
          ????????wait(future_tasks,?return_when=ALL_COMPLETED)

          ????wb.save(filename='data2.xlsx')
          ????delta?=?(datetime.now()?-?start).total_seconds()
          ????print(f'用時:{delta}s')


          run()
          運(yùn)行結(jié)果如下:
          多線程爬蟲爬取效率提升非??捎^,用時 2.648128s,爬取速度很快。

          五、異步協(xié)程爬蟲

          #?-*-?coding:?UTF-8?-*-
          """
          @File ???:demo1.py
          @Author ?:葉庭云
          @CSDN ???:https://yetingyun.blog.csdn.net/
          """

          import?aiohttp
          import?asyncio
          import?logging
          from?fake_useragent?import?UserAgent
          from?lxml?import?etree
          import?openpyxl
          from?datetime?import?datetime

          #?日志輸出的基本配置
          logging.basicConfig(level=logging.INFO,?format='%(asctime)s?-?%(levelname)s:?%(message)s')
          #?隨機(jī)產(chǎn)生請求頭
          ua?=?UserAgent(verify_ssl=False,?path='fake_useragent.json')
          wb?=?openpyxl.Workbook()
          sheet?=?wb.active
          sheet.append(['品名',?'最新報(bào)價(jià)',?'單位',?'報(bào)價(jià)數(shù)',?'報(bào)價(jià)時間'])
          start?=?datetime.now()


          class?Spider(object):
          ????def?__init__(self):
          ????????#?self.semaphore?=?asyncio.Semaphore(6)??#?信號量,有時候需要控制協(xié)程數(shù),防止爬的過快被反爬
          ????????self.header?=?{
          ????????????????"Accept-Encoding":?"gzip",????#?使用gzip壓縮傳輸數(shù)據(jù)讓訪問更快
          ????????????????"User-Agent":?ua.random
          ????????????}

          ????async?def?scrape(self,?url):
          ????????#?async?with?self.semaphore:??#?設(shè)置最大信號量,有時候需要控制協(xié)程數(shù),防止爬的過快被反爬
          ????????session?=?aiohttp.ClientSession(headers=self.header,?connector=aiohttp.TCPConnector(ssl=False))
          ????????response?=?await?session.get(url)
          ????????result?=?await?response.text()
          ????????await?session.close()
          ????????return?result

          ????async?def?scrape_index(self,?page):
          ????????url?=?f'https://www.zhongnongwang.com/quote/product-htm-page-{page}.html'
          ????????text?=?await?self.scrape(url)
          ????????await?self.parse(text)

          ????async?def?parse(self,?text):
          ????????#?Xpath定位提取數(shù)據(jù)
          ????????html?=?etree.HTML(text)
          ????????items?=?html.xpath('/html/body/div[10]/table/tr[@align="center"]')
          ????????logging.info(f'該頁有多少條信息:{len(items)}')??#?一頁有20條信息
          ????????#?遍歷提取出數(shù)據(jù)
          ????????for?item?in?items:
          ????????????name?=?''.join(item.xpath('.//td[1]/a/text()'))??#?品名
          ????????????price?=?''.join(item.xpath('.//td[3]/text()'))??#?最新報(bào)價(jià)
          ????????????unit?=?''.join(item.xpath('.//td[4]/text()'))??#?單位
          ????????????nums?=?''.join(item.xpath('.//td[5]/text()'))??#?報(bào)價(jià)數(shù)
          ????????????time_?=?''.join(item.xpath('.//td[6]/text()'))??#?報(bào)價(jià)時間
          ????????????sheet.append([name,?price,?unit,?nums,?time_])
          ????????????logging.info([name,?price,?unit,?nums,?time_])

          ????def?main(self):
          ????????#?50頁的數(shù)據(jù)
          ????????scrape_index_tasks?=?[asyncio.ensure_future(self.scrape_index(page))?for?page?in?range(1,?51)]
          ????????loop?=?asyncio.get_event_loop()
          ????????tasks?=?asyncio.gather(*scrape_index_tasks)
          ????????loop.run_until_complete(tasks)


          if?__name__?==?'__main__':
          ????spider?=?Spider()
          ????spider.main()
          ????wb.save('data3.xlsx')
          ????delta?=?(datetime.now()?-?start).total_seconds()
          ????print("用時:{:.3f}s".format(delta))
          運(yùn)行結(jié)果如下:
          而到了協(xié)程異步爬蟲,爬取速度更快,嗖的一下,用時 0.930s 就爬取完 50 頁數(shù)據(jù),aiohttp + asyncio 異步爬蟲竟恐怖如斯。異步爬蟲在服務(wù)器能承受高并發(fā)的前提下增加并發(fā)數(shù)量,爬取效率提升是非??捎^的,比多線程還要快一些。
          三種爬蟲都將 50 頁的數(shù)據(jù)爬取下來保存到了本地,結(jié)果如下:

          六、總結(jié)回顧

          今天我演示了簡單的單線程爬蟲、多線程爬蟲和協(xié)程異步爬蟲??梢钥吹揭话闱闆r下異步爬蟲速度最快,多線程爬蟲略慢一點(diǎn),單線程爬蟲速度較慢,必須上一個頁面爬取完成才能繼續(xù)爬取。
          但協(xié)程異步爬蟲相對來說并不是那么好編寫,數(shù)據(jù)抓取無法使用 request 庫,只能使用aiohttp,而且爬取數(shù)據(jù)量大時,異步爬蟲需要設(shè)置最大信號量來控制協(xié)程數(shù),防止爬的過快被反爬。所以在實(shí)際編寫 Python 爬蟲時,我們一般都會使用多線程爬蟲來提速,但必須注意的是網(wǎng)站都有 ip 訪問頻率限制,爬的過快可能會被封ip,所以一般我們在多線程提速的同時可以使用代理 ip 來并發(fā)地爬取數(shù)據(jù)。
          • 多線程(multithreading):是指從軟件或者硬件上實(shí)現(xiàn)多個線程并發(fā)執(zhí)行的技術(shù)。具有多線程能力的計(jì)算機(jī)因有硬件支持而能夠在同一時間執(zhí)行多于一個線程,進(jìn)而提升整體處理性能。具有這種能力的系統(tǒng)包括對稱多處理機(jī)、多核心處理器以及芯片級多處理或同時多線程處理器。在一個程序中,這些獨(dú)立運(yùn)行的程序片段叫作 "線程" (Thread),利用它編程的概念就叫作 "多線程處理"。
          • 異步(asynchronous):為完成某個任務(wù),不同程序單元之間過程中無需通信協(xié)調(diào),也能完成任務(wù)的方式,不相關(guān)的程序單元之間可以是異步的。例如,爬蟲下載網(wǎng)頁。調(diào)度程序調(diào)用下載程序后,即可調(diào)度其他任務(wù),而無需與該下載任務(wù)保持通信以協(xié)調(diào)行為。不同網(wǎng)頁的下載、保存等操作都是無關(guān)的,也無需相互通知協(xié)調(diào)。這些異步操作的完成時刻并不確定。簡言之,異步意味著無序
          • 協(xié)程(coroutine),又稱微線程、纖程,協(xié)程是一種用戶態(tài)的輕量級線程。協(xié)程擁有自己的寄存器上下文和棧。協(xié)程調(diào)度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復(fù)先前保存的寄存器上下文和棧。因此協(xié)程能保留上一次調(diào)用時的狀態(tài),即所有局部狀態(tài)的一個特定組合,每次過程重入時,就相當(dāng)于進(jìn)入上一次調(diào)用的狀態(tài)。協(xié)程本質(zhì)上是個單進(jìn)程,協(xié)程相對于多進(jìn)程來說,無需線程上下文切換的開銷,無需原子操作鎖定及同步的開銷,編程模型也非常簡單。我們可以使用協(xié)程來實(shí)現(xiàn)異步操作,比如在網(wǎng)絡(luò)爬蟲場景下,我們發(fā)出一個請求之后,需要等待一定的時間才能得到響應(yīng),但其實(shí)在這個等待過程中,程序可以干許多其他的事情,等到響應(yīng)得到之后才切換回來繼續(xù)處理,這樣可以充分利用 CPU 和其他資源,這就是協(xié)程的優(yōu)勢。
          作者:葉庭云?
          CSDN:https://yetingyun.blog.csdn.net/
          熱愛可抵歲月漫長,發(fā)現(xiàn)求知的樂趣,在不斷總結(jié)和學(xué)習(xí)中進(jìn)步,與諸君共勉。

          更多閱讀



          2020 年最佳流行 Python 庫 Top 10


          2020 Python中文社區(qū)熱門文章 Top 10


          5分鐘快速掌握 Python 定時任務(wù)框架

          特別推薦




          點(diǎn)擊下方閱讀原文加入社區(qū)會員

          瀏覽 38
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  黄色亚洲干日本 | 美女尻屄网站 | 色先锋影音 | 国产骚婷婷| 国产成人a亚洲精品 |