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

          哈哈,有人爬我網(wǎng)站,我把他教育了一頓!

          共 3974字,需瀏覽 8分鐘

           ·

          2024-04-11 15:38

          Python客棧設(shè)為“星標(biāo)?
          第一時(shí)間收到最新資訊

          作為一個(gè)站長(zhǎng),你是不是對(duì)爬蟲不勝其煩?爬蟲天天來(lái)爬,速度又快,頻率又高,服務(wù)器的大量資源被白白浪費(fèi)。

          看這篇文章的你有福了,我們今天一起來(lái)報(bào)復(fù)一下爬蟲,直接把爬蟲的服務(wù)器給干死機(jī)。

          本文有一個(gè)前提:你已經(jīng)知道某個(gè)請(qǐng)求是爬蟲發(fā)來(lái)的了,你不滿足于單單屏蔽對(duì)方,而是想搞死對(duì)方。

          很多人的爬蟲是使用Requests來(lái)寫的,如果你閱讀過(guò)Requests的文檔,那么你可能在文檔中的Binary Response Content[1]這一小節(jié),看到這樣一句話:

          The gzip and deflate transfer-encodings are automatically decoded for you.
          (Request)會(huì)自動(dòng)為你把gzip和deflate轉(zhuǎn)碼后的數(shù)據(jù)進(jìn)行解碼

          網(wǎng)站服務(wù)器可能會(huì)使用gzip壓縮一些大資源,這些資源在網(wǎng)絡(luò)上傳輸?shù)臅r(shí)候,是壓縮后的二進(jìn)制格式??蛻舳耸盏椒祷匾院?,如果發(fā)現(xiàn)返回的Headers里面有一個(gè)字段叫做Content-Encoding,其中的值包含gzip,那么客戶端就會(huì)先使用gzip對(duì)數(shù)據(jù)進(jìn)行解壓,解壓完成以后再把它呈現(xiàn)到客戶端上面。瀏覽器自動(dòng)就會(huì)做這個(gè)事情,用戶是感知不到這個(gè)事情發(fā)生的。而requests、Scrapy這種網(wǎng)絡(luò)請(qǐng)求庫(kù)或者爬蟲框架,也會(huì)幫你做這個(gè)事情,因此你不需要手動(dòng)對(duì)網(wǎng)站返回的數(shù)據(jù)解壓縮。

          這個(gè)功能原本是一個(gè)方便開發(fā)者的功能,但我們可以利用這個(gè)功能來(lái)做報(bào)復(fù)爬蟲的事情。

          我們首先寫一個(gè)客戶端,來(lái)測(cè)試一下返回gzip壓縮數(shù)據(jù)的方法。

          我首先在硬盤上創(chuàng)建一個(gè)文本文件text.txt,里面有兩行內(nèi)容,如下圖所示:

          然后,我是用gzip命令把它壓縮成一個(gè).gz文件:

          cat text.txt | gzip > data.gz

          接下來(lái),我們使用FastAPI寫一個(gè)HTTP服務(wù)器server.py

          from fastapi import FastAPI, Response
          from fastapi.responses import FileResponse


          app = FastAPI()


          @app.get('/')
          def index():
              resp = FileResponse('data.gz')
              return resp

          然后使用命令uvicorn server:app啟動(dòng)這個(gè)服務(wù)。

          接下來(lái),我們使用requests來(lái)請(qǐng)求這個(gè)接口,會(huì)發(fā)現(xiàn)返回的數(shù)據(jù)是亂碼,如下圖所示:

          返回的數(shù)據(jù)是亂碼,這是因?yàn)榉?wù)器沒(méi)有告訴客戶端,這個(gè)數(shù)據(jù)是gzip壓縮的,因此客戶端只有原樣展示。由于壓縮后的數(shù)據(jù)是二進(jìn)制內(nèi)容,強(qiáng)行轉(zhuǎn)成字符串就會(huì)變成亂碼。

          現(xiàn)在,我們稍微修改一下server.py的代碼,通過(guò)Headers告訴客戶端,這個(gè)數(shù)據(jù)是經(jīng)過(guò)gzip壓縮的:

          from fastapi import FastAPI, Response
          from fastapi.responses import FileResponse


          app = FastAPI()


          @app.get('/')
          def index():
              resp = FileResponse('data.gz')
              resp.headers['Content-Encoding'] = 'gzip'  # 說(shuō)明這是gzip壓縮的數(shù)據(jù)
              return resp

          修改以后,重新啟動(dòng)服務(wù)器,再次使用requests請(qǐng)求,發(fā)現(xiàn)已經(jīng)可以正常顯示數(shù)據(jù)了:

          這個(gè)功能已經(jīng)展示完了,那么我們?cè)趺蠢盟??這就不得不提到壓縮文件的原理了。

          文件之所以能壓縮,是因?yàn)槔锩嬗写罅恐貜?fù)的元素,這些元素可以通過(guò)一種更簡(jiǎn)單的方式來(lái)表示。壓縮的算法有很多種,其中最常見的一種方式,我們用一個(gè)例子來(lái)解釋。假設(shè)有一個(gè)字符串,它長(zhǎng)成下面這樣:

          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111
          1111111111111111

          我們可以用5個(gè)字符來(lái)表示:192個(gè)1。這就相當(dāng)于把192個(gè)字符壓縮成了5個(gè)字符,壓縮率高達(dá)97.4%。

          如果我們可以把一個(gè)1GB的文件壓縮成1MB,那么對(duì)服務(wù)器來(lái)說(shuō),僅僅是返回了1MB的二進(jìn)制數(shù)據(jù),不會(huì)造成任何影響。但是對(duì)客戶端或者爬蟲來(lái)說(shuō),它拿到這個(gè)1MB的數(shù)據(jù)以后,就會(huì)在內(nèi)存中把它還原成1GB的內(nèi)容。這樣一瞬間爬蟲占用的內(nèi)存就增大了1GB。如果我們?cè)龠M(jìn)一步增大這個(gè)原始數(shù)據(jù),那么很容易就可以把爬蟲所在的服務(wù)器內(nèi)存全部沾滿,輕者服務(wù)器直接殺死爬蟲進(jìn)程,重則爬蟲服務(wù)器直接死機(jī)。

          你別以為這個(gè)壓縮比聽起來(lái)很夸張,其實(shí)我們使用很簡(jiǎn)單的一行命令就可以生成這樣的壓縮文件。

          如果你用的是Linux,那么請(qǐng)執(zhí)行命令:

          dd if=/dev/zero bs=1M count=1000 | gzip > boom.gz

          如果你的電腦是macOS,那么請(qǐng)執(zhí)行命令:

          dd if=/dev/zero bs=1048576 count=1000 | gzip > boom.gz

          執(zhí)行過(guò)程如下圖所示:

          生成的這個(gè)boom.gz文件只有995KB。但是如果我們使用gzip -d boom.gz對(duì)這個(gè)文件解壓縮,就會(huì)發(fā)現(xiàn)生成了一個(gè)1GB的boom文件,如下圖所示:

          只要大家把命令里面的count=1000改成一個(gè)更大的數(shù)字,就能得到更大的文件。

          我現(xiàn)在把count改成10,給大家做一個(gè)演示(不敢用1GB的數(shù)據(jù)來(lái)做測(cè)試,害怕我的Jupyter崩潰)。生成的boom.gz文件只有10KB:

          服務(wù)器返回一個(gè)10KB的二進(jìn)制數(shù)據(jù),沒(méi)有任何問(wèn)題。

          現(xiàn)在我們用requests去請(qǐng)求這個(gè)接口,然后查看一下resp這個(gè)對(duì)象占用的內(nèi)存大?。?/p>

          可以看到,由于requests自動(dòng)會(huì)對(duì)返回的數(shù)據(jù)解壓縮,因此最終獲得的resp對(duì)象竟然有10MB這么大。

          如果大家想使用這個(gè)方法,一定要先確定這個(gè)請(qǐng)求是爬蟲發(fā)的,再使用。否則被你干死的不是爬蟲而是真實(shí)用戶就麻煩了。

          本文的寫作過(guò)程中,參考了文章網(wǎng)站gzip炸彈 – 王春偉的技術(shù)博客[2],特別感謝原作者。

          參考文獻(xiàn)

          [1] Binary Response Content: https://2.python-requests.org/en/master/user/quickstart/#binary-response-content

          [2] 網(wǎng)站gzip炸彈 – 王春偉的技術(shù)博客: http://da.dadaaierer.com/?p=577



          往期回顧

          1、首個(gè)AI軟件工程師震撼硅谷!手握10塊IOI金牌,他們鐵了心砸掉程序員飯碗
          2、程序員瘋狂互爆每年薪資變化。
          3、國(guó)產(chǎn)電視盒子瘋狂破解路由器 這是想干啥?
          4、昔日手機(jī)巨頭要退出中國(guó)大陸市場(chǎng)?11年堅(jiān)持化成泡影
          5、每次看到她寫的代碼,我都感到自己無(wú)比平庸


                   

          點(diǎn)擊關(guān)注公眾號(hào),閱讀更多精彩內(nèi)容

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

          手機(jī)掃一掃分享

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

          手機(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>
                  色网在线看 | 成人av影视在线观看国产高清 | 亚洲精品中文无码视频 | 俺去也俺来也在线www官网 | 欧美色图一区在线视频 |