關於urllib、urllib2爬蟲偽裝的總結


站在網站管理的角度,如果在同一時間段,大家全部利用爬蟲程序對自己的網站進行爬取操作,那么這網站服務器能不能承受這種負荷?肯定不能啊,如果嚴重超負荷則會時服務器宕機(死機)的,對於一些商業型的網站,宕機一秒鍾的損失都是不得了的,這不是一個管理員能承擔的,對吧?那管理員會網站服務器做什么來優化呢?我想到的是,寫一個腳本,當檢測到一個IP訪問的速度過快,報文頭部並不是瀏覽器的話,那么就拒絕服務,或者屏蔽IP等,這樣就可以減少服務器的負擔並讓服務器正常進行。

那么既然服務器做好了優化,但你知道這是對爬蟲程序的優化,如果你是用瀏覽器來作為一個用戶訪問的話,服務器是不會攔截或者屏蔽你的,它也不敢攔你,為什么,你現在是客戶,它敢攔客戶,不想繼續經營了是吧?所以對於如果是一個瀏覽器用戶的話,是可以正常訪問的。

所以想到方法了嗎?是的,把程序偽造成一個瀏覽器啊,前面說過服務器會檢測報文頭部信息,如果是瀏覽器就不正常通行,如果是程序就拒絕服務。

那么報文是什么?頭部信息又是什么?詳細的就不解釋了,這涉及到http協議和tcp/ip三次握手等等的網絡基礎知識,感興趣的自己百度或者谷歌吧。

本篇博文不扯遠了,只說相關的重點——怎么查看頭部信息。

 

User-Agent

其實我想有些朋友可能有疑惑,服務器是怎么知道我們使用的是程序或者瀏覽器呢?它用什么來判斷的?

我使用的是火狐瀏覽器,鼠標右鍵-查看元素(有的瀏覽器是審查元素或者檢查)

 

網絡(有的是network):

 

出現報文:

雙擊它, 右邊則會出現詳細的信息,選擇消息頭(有的是headers)

找到請求頭(request headers),其中的User-Agent就是我們頭部信息:

看到是顯示的

User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0。
這就是我們的頭部信息。看到沒,顯示的信息,使用的操作系統內核是6.1,對應win7的64位,用的firefox56,就是火狐瀏覽器版本56
 
那么瀏覽器訪問的都能察覺,自然我們用的程序訪問一樣可以察覺,不管他是怎么識別的。其實如果我是管理員(如果我干了我學的專業的話,還就真的是管理員了),按我的想法的話,我直接定義個合法報文頭都得是【Mozilla/5.0……】之類的就行,除了這些其他全部拒絕是不是就可以了?
 
前面只用了urllib模塊的urlopen方法打開網頁,其下還有個功能就可以查看頭部信息,但和瀏覽器查看的有些差別。
 
注意:以下代碼都是在python2中,python3中不存在urllib和urllib2模塊,在python3中,把相關的urllib模塊組合成了一個包,都在urllib包下
復制代碼
# -*- coding:utf-8 -*-
import urllib

url='http://www.baidu.com' #百度網址
html=urllib.urlopen(url)#利用模塊urllib里的urlopen方法打開網頁
print(dir(html))  #查看對象html的方法
print(urllib.urlopen) #查看對象urllib.urlopen的方法
print(urllib.urlopen()) #查看對象urllib.urlopen實例化后的方法
復制代碼

 

結果:
復制代碼
Traceback (most recent call last):
  File "D:\programme\PyCharm 5.0.3\helpers\pycharm\utrunner.py", line 121, in <module>
    modules = [loadSource(a[0])]
  File "D:\programme\PyCharm 5.0.3\helpers\pycharm\utrunner.py", line 41, in loadSource
    module = imp.load_source(moduleName, fileName)
  File "G:\programme\Python\python project\test.py", line 8, in <module>
    print(urllib.urlopen())
TypeError: urlopen() takes at least 1 argument (0 given)

['__doc__', '__init__', '__iter__', '__module__', '__repr__', 'close', 'code', 
'fileno', 'fp', 'getcode', 'geturl', 'headers', 'info', 'next', 'read', 'readline', 'readlines', 'url']

<function urlopen at 0x0297FD30>
復制代碼
由此,這里就必須注意,只有當urllib.urlopen()實例化后才有其后面的方法,urlopen會返回一個類文件對象,urllib.urlopen只是一個對象,而urllib.urlopen()必須傳入一個參數,不然則報錯。
在前一章已經用過有效實例化后的read()方法,可以讀取得到的網站信息。

urlopen提供了如下方法:

  • read() , readline() , readlines() , fileno() , close() :這些方法的使用方式與文件對象完全一樣
  • info():返回一個httplib.HTTPMessage 對象,表示遠程服務器返回的頭信息
  • getcode():返回Http狀態碼。如果是http請求,200表示請求成功完成;404表示網址未找到
  • geturl():返回請求的url
  • headers:返回請求頭部信息
  • code:返回狀態碼
  • url:返回請求的url

 好的,詳細的自己去研究了,本篇博文的重點終於來了,偽裝一個頭部信息

 

 

偽造頭部信息

由於urllib沒有偽造頭部信息的方法,所以這里得使用一個新的模塊,urllib2

 

復制代碼
# -*- coding:utf-8 -*-
import urllib2

url='http://www.baidu.com'

head={
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0'
}  #頭部信息,必須是一個字典
html=urllib2.Request(url,headers=head)
result=urllib2.urlopen(html)
print result.read()
復制代碼

或者你也可以這樣:

復制代碼
# -*- coding:utf-8 -*-
import urllib2

url='http://www.baidu.com'


html=urllib2.Request(url)
html.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0')  #此時注意區別格式
result=urllib2.urlopen(html)
print result.read()
復制代碼

結果都一樣的,我也就不展示了。

按照上面的方法就可以偽造請求頭部信息。

 

那么你說,我怎么知道偽造成功了?還有不偽造頭部信息時,顯示的到底是什么呢?介紹一個抓包工具——fidder,用這個工具就可以查看到底報文頭部是什么了。這里就不展示了,自己下去常識了。並且我可以確切的保證,確實偽造成功了。

這樣,我們就把爬蟲代碼升級了一下,可以搞定普通的反爬蟲限制


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM