1. 使用.Net Core做個(gè)爬蟲(chóng)

        共 2767字,需瀏覽 6分鐘

         ·

        2020-12-23 22:40

          最近接手一個(gè)新項(xiàng)目,爬亞馬遜分類、商品數(shù)據(jù)。記得大學(xué)的時(shí)候,自己瞎玩,寫(xiě)過(guò)一個(gè)爬有緣網(wǎng)數(shù)據(jù)的程序,那個(gè)時(shí)候沒(méi)有考慮那么多,寫(xiě)的還是單線程,因?yàn)榫W(wǎng)站沒(méi)有反爬,就不停的一直請(qǐng)求,記得放到實(shí)驗(yàn)室電腦上一天,跑了30w+的數(shù)據(jù)。然后當(dāng)前晚上有緣網(wǎng)網(wǎng)站顯示維護(hù)中。。。。

        ?畢竟小打小鬧,沒(méi)有真正的寫(xiě)過(guò)爬蟲(chóng)。就翻別人博客了解了下爬蟲(chóng)所用到的技術(shù)、技巧、套路。然后就翻到這個(gè)老哥寫(xiě)的博客, 雖然語(yǔ)言是有點(diǎn)囂張,但是我還是比較認(rèn)同的 哈哈哈哈。

        ?

        ?下面從爬蟲(chóng)涉及的幾任務(wù)調(diào)度、數(shù)據(jù)去重、數(shù)據(jù)解析、并發(fā)控制、斷點(diǎn)續(xù)爬、代理來(lái)聊聊項(xiàng)目遇到的坑。

        一、數(shù)據(jù)解析

        數(shù)據(jù)解析就是提取網(wǎng)頁(yè)上的有效數(shù)據(jù)。.Net下有個(gè)HtmlAgilityPack組件,可以很好地解析HMTL。想都沒(méi)想 就直接用了它(這就為后面挖了一個(gè)大坑)。剛開(kāi)始單線程測(cè)試的時(shí)候,一切正常,但是當(dāng)我開(kāi)了50個(gè)線程的時(shí)候,內(nèi)存在90s內(nèi)飆升到了3G,而且持續(xù)爬升。

        用.Net Memory工具分析發(fā)現(xiàn) 內(nèi)存被大對(duì)象沾滿了,所以每次GC的時(shí)候內(nèi)存并沒(méi)有被回收,有5w多HtmlNode,每個(gè)對(duì)象大小都超過(guò) 85000byte。

        ?因?yàn)閬嗰R遜的圖片不是通過(guò)鏈接外鏈的,而是通過(guò)base64編碼的,所以導(dǎo)致下載的網(wǎng)頁(yè)Html超過(guò)1M,而85000byte就算大對(duì)象了。導(dǎo)致每爬取一個(gè)商品詳情頁(yè),都會(huì)加載到HtmlNode中變成一個(gè)大對(duì)象,由于GC不壓縮大對(duì)象,而C對(duì)大對(duì)象的回收只有在回收2代的時(shí)候才觸發(fā)。所以只能改變策略,通過(guò)正則、切分字符串來(lái)處理。

        二、任務(wù)調(diào)度、并行爬取

        目的是爬取亞馬遜的分類和分類下的商品,我做了個(gè)3個(gè)任務(wù),

        1、找到分類入口,爬取分類Id、標(biāo)題、url 、分類等級(jí)存儲(chǔ)到數(shù)據(jù)庫(kù)。

        2、根據(jù)1任務(wù)爬取的分類Id,獲取分類下商品列表。爬取列表上商品部分信息,包括商品的Id、名稱、縮略圖。

        3、根據(jù)2任務(wù)爬取的商品Id,獲取商品詳情頁(yè),爬取商品詳情頁(yè)的其他信息。

        一個(gè)分類下有幾百頁(yè)商品列表,而每個(gè)列表一般有22個(gè)商品。所以1任務(wù)爬取完一次,2任務(wù)要爬取幾百次(當(dāng)然不會(huì)將分類下的所有頁(yè)碼都爬完,設(shè)定只爬20頁(yè)) ,3任務(wù)要爬 20 x 22次。這樣分任務(wù)的好處就是 3個(gè)任務(wù)中,不論哪個(gè)任務(wù)掛了,其他2個(gè)任務(wù)是不受影響的,可以繼續(xù)跑。

        比如2任務(wù)掛掉了,1任務(wù)不受它影響,雖然3任務(wù)的需要2任務(wù)的數(shù)據(jù),但是3任務(wù)的速度是比2任務(wù)慢了22倍還多(獲取詳情的時(shí)候 還需要在請(qǐng)求其他頁(yè)面)所以任務(wù)線程相同的情況下 2任務(wù)的會(huì)有很多剩余商品 3還沒(méi)有來(lái)得及跑。

        調(diào)度采用了QuartZ 使用Cron配置定時(shí)任務(wù)。使用Parallel并行爬取,線程數(shù)量可以配只需要將方法和方法所需要的參數(shù)集合放到ForEach

        ?

        合理配置每個(gè)任務(wù)的線程數(shù)量,我設(shè)置爬取分類線程數(shù)1,商品列表的線程是2,商品詳情爬取線程為50。爬取的速度不同線程數(shù)量就不同,而且并不是線程越高越好,這個(gè)值是不斷的調(diào)試采集相同時(shí)間的數(shù)據(jù)分析得出來(lái)的。

        三、代理

        現(xiàn)在有很多代理商,普遍分為兩種:

          第一種通過(guò)接口返回代理IP和這個(gè)代理的可用時(shí)間,在這個(gè)時(shí)間段內(nèi),這個(gè)代理是可用的。注意:這種代理方式需要有個(gè)代理池,因?yàn)榕老x(chóng)一般都是多線程,如果在代理IP可用時(shí)間段內(nèi),多個(gè)線程一直使用同一個(gè)代理IP,很大可能會(huì)被封。所以保險(xiǎn)的做法就是一個(gè)線程一個(gè)代理,降低每個(gè)代理的請(qǐng)求次數(shù)。

          第二種代理直接給你一個(gè)固定的IP,這個(gè)代理IP沒(méi)有時(shí)間限制,代理商那邊會(huì)幫你自動(dòng)幫你換不同的IP請(qǐng)求目標(biāo)地址。

        .Net Core中使用代理很簡(jiǎn)單,因?yàn)槲沂褂玫氖荋ttpClientFactory,所以在添加服務(wù)的時(shí)候配置 HttpClientHandler的代理就可以,需要實(shí)現(xiàn)一個(gè)IWebProxy類,返回對(duì)應(yīng)的代理IP和端口號(hào)就可以了。

        ?剛開(kāi)始使用的是第一種代理,為了實(shí)現(xiàn)一個(gè)線程一個(gè)代理,我創(chuàng)建了一個(gè)代理池,在程序啟動(dòng)的時(shí)候,每個(gè)線程都會(huì)從代理商那獲取到一個(gè)代理IP,然后放到代理池中,每次獲取代理的時(shí)候,通過(guò)代理池中隨機(jī)挑選一個(gè)代理IP,在挑選前會(huì)判斷當(dāng)前代理池中的代理數(shù)量,如果小于線程數(shù)據(jù),就會(huì)去獲取填充到代理池中。

        后面發(fā)現(xiàn)國(guó)內(nèi)的代理商的IP訪問(wèn)國(guó)外網(wǎng)址太慢了,就換了國(guó)外代理,國(guó)外代理使用的是第二種方案。但是這個(gè)代理商不是自動(dòng)幫你更換IP,而是需要每次傳遞一個(gè)隨機(jī)數(shù) SessionId,隨機(jī)數(shù)不同,代理商訪問(wèn)目標(biāo)網(wǎng)站的IP就不同,而且要傳用戶名和密碼。

        ?開(kāi)始 我是這么做的:

        ?發(fā)現(xiàn)這種只有在第一次創(chuàng)建HttpClient的時(shí)候才會(huì)去走配置ConfigurePrimaryHttpMessageHandler方法,之后創(chuàng)建HttpClient都不會(huì)走。就導(dǎo)致一直在使用同一個(gè)IP請(qǐng)求。

        所以沒(méi)辦法,只能放棄使用HttpClientFactory,自己手動(dòng)創(chuàng)建HttpClient ,然后釋放。但這種又隨之帶來(lái)一個(gè)問(wèn)題HttpClient雖然釋放了,但是端口還是被占用著,目前還沒(méi)有好的解決辦法。

        ?四、斷點(diǎn)續(xù)爬、數(shù)據(jù)去重

        我這個(gè)業(yè)務(wù)中這兩個(gè)功能就很好實(shí)現(xiàn),每次爬取完成商品頁(yè)碼,就存儲(chǔ)下一頁(yè)的頁(yè)碼和當(dāng)前爬取的頁(yè)碼數(shù)。配置一個(gè)參數(shù)是否是斷點(diǎn)續(xù)爬,如果是斷點(diǎn)續(xù)爬,就從上次記錄的頁(yè)碼爬取商品。

        數(shù)據(jù)去重,因?yàn)橹苯涌梢阅玫絹嗰R遜的商品Id和分類Id,所以去重就變的很簡(jiǎn)單,任務(wù)啟動(dòng)的時(shí)候,會(huì)將已經(jīng)爬取過(guò)的商品Id和分類Id放到緩存中,爬取的時(shí)候?qū)Ρ葦?shù)據(jù)。

        ?

        項(xiàng)目在服務(wù)器上跑了2個(gè)晚上,表現(xiàn)還是可以的,數(shù)據(jù)都正確采集到了117w數(shù)據(jù)(包含未爬取詳情的商品),最后的最后。。。。項(xiàng)目被砍了,因?yàn)閬嗰R遜的商品詳情頁(yè)數(shù)據(jù)太大,導(dǎo)致爬了12個(gè)小時(shí)用了40G流量,1G=6美元 ,一個(gè)月就要40x2x6x30=14400美元。忙碌了兩周,也算從零寫(xiě)了一個(gè)小小的爬蟲(chóng),還算有所得。

        出處:https://www.cnblogs.com/MicroHeart/p/14115853.html







        回復(fù)?【關(guān)閉】學(xué)關(guān)
        回復(fù)?【實(shí)戰(zhàn)】獲取20套實(shí)戰(zhàn)源碼
        回復(fù)?【被刪】學(xué)個(gè)
        回復(fù)?【訪客】學(xué)
        回復(fù)?【小程序】學(xué)獲取15套【入門+實(shí)戰(zhàn)+賺錢】小程序源碼
        回復(fù)?【python】學(xué)微獲取全套0基礎(chǔ)Python知識(shí)手冊(cè)
        回復(fù)?【2019】獲取2019 .NET 開(kāi)發(fā)者峰會(huì)資料PPT
        回復(fù)?【加群】加入dotnet微信交流群

        再見(jiàn),VIP,臥槽又來(lái)一個(gè)看片神器!


        推薦這10個(gè)優(yōu)秀的.NET Core開(kāi)源項(xiàng)目!



        瀏覽 56
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 日韩精品一卡二卡三卡四卡1 | 亚洲电影一区 | 四虎永久免费在线 | 8050午夜一级少妇电影院 | 午夜视频在线观看一区 |