1.怎樣扒網頁呢净神?
其實就是根據URL來獲取它的網頁信息何吝,雖然我們在瀏覽器中看到的是一幅幅優(yōu)美的畫面,但是其實是由瀏覽器解釋才呈現出來的鹃唯,實質它是一段HTML代碼爱榕,加 JS、CSS坡慌,如果把網頁比作一個人黔酥,那么HTML便是他的骨架,JS便是他的肌肉洪橘,CSS便是它的衣服跪者。所以最重要的部分是存在于HTML中的,下面我們就寫個例子來扒一個網頁下來
from urllib.request import urlopen
response = urlopen("http://www.baidu.com")
print(response.read().decode())
真正的程序就兩行
?2. 常見到的方法
1)requset.urlopen(url,data,timeout)
? ? - 第一個參數url即為URL熄求,第二個參數data是訪問URL時要傳送的數據渣玲,第三個timeout是設置超時時間。
? ? - 第二三個參數是可以不傳送的弟晚,data默認為空None忘衍,timeout默認為 socket._GLOBAL_DEFAULT_TIMEOUT
? ? - 第一個參數URL是必須要傳送的,在這個例子里面我們傳送了百度的URL卿城,執(zhí)行urlopen方法之后枚钓,返回一個response對象,返回信息便保存在這里面瑟押。
2)response.read()
? ? - read()方法就是讀取文件里的全部內容搀捷,返回bytes類型
3)response.getcode()
? ? - 返回 HTTP的響應碼,成功返回200勉耀,4服務器頁面出錯指煎,5服務器問題
4)response.geturl()
? ? - 返回 返回實際數據的實際URL,防止重定向問題
5)response.info()
? ? - 返回 服務器響應的HTTP報頭
?3. Request對象
其實上面的urlopen參數可以傳入一個request請求,它其實就是一個Request類的實例便斥,構造時需要傳入Url,Data等等的內容至壤。比如上面的兩行代碼,我們可以這么改寫
from urllib.request import urlopen
from urllib.request import Request
request = Request("http://www.baidu.com")
response = urlopen(requst)
print response.read().decode()
運行結果是完全一樣的枢纠,只不過中間多了一個request對象像街,推薦大家這么寫,因為在構建請求時還需要加入好多內容,通過構建一個request镰绎,服務器響應請求得到應答脓斩,這樣顯得邏輯上清晰明確
4. Get 請求
大部分被傳輸到瀏覽器的html,images畴栖,js随静,css, … 都是通過GET方法發(fā)出請求的。它是獲取數據的主要方法
例如:www.baidu.com 搜索
Get請求的參數都是在Url中體現的,如果有中文吗讶,需要轉碼燎猛,這時我們可使用
?urllib.parse.urlencode()
?urllib.parse. quote()
5. Post 請求
我們說了Request請求對象的里有data參數,它就是用在POST里的照皆,我們要傳送的數據就是這個參數data重绷,data是一個字典,里面要匹配鍵值對
發(fā)送請求/響應header頭的含義:
名稱 | 含義
Accept | 告訴服務器膜毁,客戶端支持的數據類型
Accept-Charset | 告訴服務器昭卓,客戶端采用的編碼
Accept-Encoding | 告訴服務器,客戶機支持的數據壓縮格式
Accept-Language | 告訴服務器瘟滨,客戶機的語言環(huán)境
Host | 客戶機通過這個頭告訴服務器候醒,想訪問的主機名
If-Modified-Since | 客戶機通過這個頭告訴服務器,資源的緩存時間
Referer | 客戶機通過這個頭告訴服務器室奏,它是從哪個資源來訪問服務器的火焰。(一般用于防盜鏈)
User-Agent | 客戶機通過這個頭告訴服務器,客戶機的軟件環(huán)境
Cookie | 客戶機通過這個頭告訴服務器胧沫,可以向服務器帶數據
Refresh | 服務器通過這個頭昌简,告訴瀏覽器隔多長時間刷新一次
Content-Type | 服務器通過這個頭,回送數據的類型
Content-Language | 服務器通過這個頭绒怨,告訴服務器的語言環(huán)境
Server | 服務器通過這個頭纯赎,告訴瀏覽器服務器的類型
Content-Encoding | 服務器通過這個頭,告訴瀏覽器數據采用的壓縮格式
Content-Length | 服務器通過這個頭南蹂,告訴瀏覽器回送數據的長度
?6. 響應的編碼
響應狀態(tài)碼
響應狀態(tài)代碼有三位數字組成犬金,第一個數字定義了響應的類別,且有五種可能取值六剥。
常見狀態(tài)碼:
號碼 | 含義
100~199 | 表示服務器成功接收部分請求晚顷,要求客戶端繼續(xù)提交其余請求才能完成整個處理過程
200~299 | 表示服務器成功接收請求并已完成整個處理過程。常用200(OK 請求成功)
300~399 | 為完成請求疗疟,客戶需進一步細化請求该默。例如:請求的資源已經移動一個新地址、常用302(所請求的頁面已經臨時轉移至新的url)策彤、307和304(使用緩存資源)
400~499 | 客戶端的請求有錯誤栓袖,常用404(服務器無法找到被請求的頁面)匣摘、403(服務器拒絕訪問,權限不夠)
500~599 | 服務器端出現錯誤裹刮,常用500(請求未完成音榜。服務器遇到不可預知的情況)
?7. Ajax的請求獲取數據
有些網頁內容使用AJAX加載,而AJAX一般返回的是JSON,直接對AJAX地址進行post或get捧弃,就返回JSON數據了
?8. 請求 SSL證書驗證
現在隨處可見 https 開頭的網站赠叼,urllib可以為 HTTPS 請求驗證SSL證書,就像web瀏覽器一樣违霞,如果網站的SSL證書是經過CA認證的梅割,則能夠正常訪問,如:https://www.baidu.com/
如果SSL證書驗證不通過葛家,或者操作系統(tǒng)不信任服務器的安全證書,比如瀏覽器在訪問12306網站如:https://www.12306.cn/mormhweb/的時候泌类,會警告用戶證書不受信任癞谒。(據說 12306 網站證書是自己做的,沒有通過CA認證)
# 忽略SSL安全認證
context = ssl._create_unverified_context()
# 添加到context參數里
response = urllib.request.urlopen(request, context = context)
更進一步
1. 偽裝自己
有些網站不會同意程序直接用上面的方式進行訪問刃榨,如果識別有問題弹砚,那么站點根本不會響應,所以為了完全模擬瀏覽器的工作
1.1 設置請求頭
其中`User-Agent`代表用的哪個請求的瀏覽器
代碼如下:
from urllib.request import urlopen
from urllib.request import Request
url = 'http://www.server.com/login'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }?
request = Request(url, headers=headers)?
response = urlopen(request)?
page = response.read()?
對付防盜鏈枢希,服務器會識別headers中的referer是不是它自己桌吃,如果不是,有的服務器不會響應苞轿,所以我們還可以在headers中加入referer
代碼如下:
headers = {
? ? ? ? 'User-Agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
? ? ? ? 'Referer':'http://www.zhihu.com/articles'
? ? ? ? ? }?
注意:>在此可以使用多個User_Agent:然后隨即選擇
import urllib.request
import random
ua_list = [
? ? "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)",
? ? "Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1",
? ? "Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1",
? ? "Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27",
? ? "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ;? QIHU 360EE)"
]
user_agent = random.choice(ua_list)
request = urllib.request.Request("http://www.baidu.com")
request.add_header("User-Agent",user_agent)
#區(qū)分大小寫
print(request.get_header("User-agent"))
?1.2 設置代理Proxy
> 假如一個網站它會檢測某一段時間某個IP 的訪問次數茅诱,如果訪問次數過多,它會禁止你的訪問搬卒。所以你可以設置一些代理服務器來幫助你做工作瑟俭,每隔一段時間換一個代理,網站君都不知道是誰在搗鬼了F跹(西刺免費代理)
?分類:
1)透明代理:目標網站知道你使用了代理并且知道你的源IP地址摆寄,這種代理顯然不符合我們這里使用代理的初衷
2)匿名代理:匿名程度比較低,也就是網站知道你使用了代理坯门,但是并不知道你的源IP地址
3)高匿代理:這是最保險的方式微饥,目標網站既不知道你使用的代理更不知道你的源IP
代碼如下:
from urllib.request import ProxyHandler
from urllib.request import build_opener
proxy = ProxyHandler({"http": "119.109.197.195:80"})
opener = build_opener(proxy)
url = "http://www.baidu.com"
response = opener.open(url)
print(response.read().decode("utf-8"))
?2 .使用DebugLog
可以通過下面的方法把 Debug Log 打開,這樣收發(fā)包的內容就會在屏幕上打印出來古戴,方便調試欠橘,這個也不太常用,僅提一下
from urllib.request import HTTPHandler
from urllib.request import build_opener
from urllib.request import Request
handler = HTTPHandler(debuglevel=1)
opener = build_opener(handler)
url = "http://www.sohu.com"
request = Request(url)
response = opener.open(request)