Python3 基于asyncio的新聞爬蟲思路

      網(wǎng)友投稿 1097 2025-04-05

      ∟文章首發(fā)于我的個(gè)人博客:Python教程


      Python寫爬蟲是非常方便的,爬取的目標(biāo)不同,實(shí)現(xiàn)的方式也有很大不同。新聞爬蟲的方便之處是,新聞網(wǎng)站幾乎沒有反爬蟲策略,不好的地方是你想要爬取的新聞網(wǎng)站非常非常多。這個(gè)時(shí)候,效率就是你首要考慮的問題。

      同步循環(huán)的效率在這里相形見絀,你需要的是異步IO實(shí)現(xiàn)一個(gè)高效率的爬蟲。

      Python3.5開始,加入了新的語法,async和await這兩個(gè)關(guān)鍵字,asyncio也成了標(biāo)準(zhǔn)庫,這對(duì)于我們寫異步IO的程序來說就是如虎添翼,讓我們輕而易舉的實(shí)現(xiàn)一個(gè)定向抓取新聞的異步爬蟲。

      1. 異步爬蟲依賴的模塊

      asyncio: 標(biāo)準(zhǔn)異步模塊,實(shí)現(xiàn)python的異步機(jī)制;

      uvloop:一個(gè)用C開發(fā)的異步循環(huán)模塊,大大提高異步機(jī)制的效率;

      aiohttp: 一個(gè)異步http請(qǐng)求的模塊,用于下載網(wǎng)頁;

      urllib.parse: 解析url網(wǎng)站的模塊;

      logging: 記錄爬蟲日志;

      leveldb: Google的Key-Value數(shù)據(jù)庫,用以記錄url的狀態(tài);

      farmhash: 對(duì)url進(jìn)行hash計(jì)算作為url的唯一標(biāo)識(shí);

      sanicdb: 對(duì)aiomysql的封裝,更方便的進(jìn)行數(shù)據(jù)庫mysql操作;

      2. 異步爬蟲實(shí)現(xiàn)的流程

      2.1 新聞源列表

      本文要實(shí)現(xiàn)的異步爬蟲是一個(gè)定向抓取新聞網(wǎng)站的爬蟲,所以就需要管理一個(gè)定向源列表,這個(gè)源列表記錄了很多我們想要抓取的新聞網(wǎng)站的url,這些url指向的網(wǎng)頁叫做hub網(wǎng)頁,它們有如下特點(diǎn):

      它們是網(wǎng)站首頁、頻道首頁、最新列表等等;

      它們包含非常多的新聞頁面的鏈接;

      它們經(jīng)常被網(wǎng)站更新,以包含最新的新聞鏈接;

      它們不是包含新聞內(nèi)容的新聞頁面;

      Hub網(wǎng)頁就是爬蟲抓取的起點(diǎn),爬蟲從中提取新聞頁面的鏈接再進(jìn)行抓取。Hub網(wǎng)址可以保存在MySql數(shù)據(jù)庫中,運(yùn)維可以隨時(shí)添加、刪除這個(gè)列表;爬蟲定時(shí)讀取這個(gè)列表來更新定向抓取的任務(wù)。這就需要爬蟲中有一個(gè)循環(huán)來定時(shí)讀取hub網(wǎng)址。

      2.2 網(wǎng)址池

      異步爬蟲的所有流程不能單單用一個(gè)循環(huán)來完成,它是多個(gè)循環(huán)(至少兩個(gè))相互作用共同完成的。它們相互作用的橋梁就是“網(wǎng)址池”(用asyncio.Queue來實(shí)現(xiàn))。

      Python3 基于asyncio的新聞爬蟲思路

      這個(gè)網(wǎng)址池就是我們比較熟悉的“生產(chǎn)者-消費(fèi)者”模式。

      一方面,hub網(wǎng)址隔段時(shí)間就要進(jìn)入網(wǎng)址池,爬蟲從網(wǎng)頁提取到的新聞鏈接也有進(jìn)入到網(wǎng)址池,這是生產(chǎn)網(wǎng)址的過程;

      另一方面,爬蟲要從網(wǎng)址池中取出網(wǎng)址進(jìn)行下載,這個(gè)過程是消費(fèi)過程;

      兩個(gè)過程相互配合,就有url不斷的進(jìn)進(jìn)出出網(wǎng)址池。

      2.3 數(shù)據(jù)庫

      這里面用到了兩個(gè)數(shù)據(jù)庫:MySQL和Leveldb。前者用于保存hub網(wǎng)址、下載的網(wǎng)頁;后者用于存儲(chǔ)所有url的狀態(tài)(是否抓取成功)。

      從網(wǎng)頁提取到的很多鏈接可能已經(jīng)被 ? zhua取過了,就不必再進(jìn)行抓取,所以他們?cè)谶M(jìn)入網(wǎng)址池前就要被檢查一下,通過leveldb可以快速查看其狀態(tài)。

      3. 異步爬蟲的實(shí)現(xiàn)細(xì)節(jié)

      前面的爬蟲流程中提到兩個(gè)循環(huán):

      循環(huán)一:定時(shí)更新hub網(wǎng)站列表

      async?def?loop_get_urls(self,): ??????????print('loop_get_urls()?start')?????????? ??????????while?1:?????????????? ??????????await?self.get_urls()?#?從MySQL讀取hub列表并將hub?url放入queue ??????????????await?asyncio.sleep(50)

      循環(huán)二: 抓取網(wǎng)頁的循環(huán)

      async?def?loop_crawl(self,):?????????? ??????print('loop_crawl()?start') ??????????last_rating_time?=?time.time() ??????????asyncio.ensure_future(self.loop_get_urls()) ??????????counter?=?0 ??????????while?1: ??????????????item?=?await?self.queue.get() ??????????????url,?ishub?=?item?????????????? ??????????????self._workers?+=?1 ??????????????counter?+=?1 ??????????????asyncio.ensure_future(self.process(url,?ishub)) ??????????????span?=?time.time()?-?last_rating_time?????????????? ??????????????if?span?>?3: ??????????????????rate?=?counter?/?span?????????????????? ??????????????????print('\tloop_crawl2()?rate:%s,?counter:?%s,?workers:?%s'?%?(round(rate,?2),?counter,?self._workers)) ??????????????????last_rating_time?=?time.time() ??????????????????counter?=?0 ??????????????if?self._workers?>?self.workers_max:?????????????????? ??????????????print('======?got?workers_max,?sleep?3?sec?to?next?worker?=====') ??????????????????await?asyncio.sleep(3)

      4. asyncio 要點(diǎn):

      讀讀asyncio的文檔就可以知道它的運(yùn)行流程,這里分享一下使用時(shí)注意到的地方。

      (1)使用loop.run_until_complete(self.loop_crawl())來啟動(dòng)整個(gè)程序的主循環(huán);

      (2)使用asyncio.ensure_future() 來異步調(diào)用一個(gè)函數(shù),它相當(dāng)于多進(jìn)程的fork,gevent的spawn(),具體可以參考上述代碼。

      Python

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:表格不自動(dòng)計(jì)算是怎么回事(表格不能自動(dòng)計(jì)算是什么原因)
      下一篇:在表格里打不了字怎么辦(表格里面打不了字怎么辦)
      相關(guān)文章
      国产成人亚洲精品影院| 亚洲国产一区明星换脸| 久久亚洲精品成人777大小说| 国产成人精品亚洲精品| 国产精品V亚洲精品V日韩精品| 日批日出水久久亚洲精品tv| 狠狠入ady亚洲精品| 精品亚洲福利一区二区| 色欲aⅴ亚洲情无码AV| 337p日本欧洲亚洲大胆人人 | 亚洲av网址在线观看| 亚洲av无码专区国产乱码在线观看| 亚洲色爱图小说专区| 国产亚洲综合色就色| 亚洲AV无码一区东京热| 亚洲欧洲日产国产综合网| 久久亚洲AV成人出白浆无码国产| 久久精品国产亚洲AV香蕉| 亚洲国产高清在线精品一区| 亚洲一区在线视频| 亚洲日韩看片无码电影| 人人狠狠综合久久亚洲| 亚洲成人国产精品| 亚洲一区AV无码少妇电影☆| 日韩亚洲人成在线综合日本| 亚洲一区二区影院| 亚洲乱码卡三乱码新区| 亚洲欧美日韩综合久久久久| 国产成人人综合亚洲欧美丁香花 | 国产AV无码专区亚洲AV麻豆丫| 亚洲不卡AV影片在线播放| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 亚洲A∨无码无在线观看| 18亚洲男同志videos网站| 亚洲午夜电影一区二区三区| 亚洲日本中文字幕天天更新| 婷婷亚洲综合五月天小说在线| 亚洲精品456播放| 九月丁香婷婷亚洲综合色| 亚洲美女免费视频| 亚洲乱码国产乱码精华|