天天看點

爬蟲基礎 ----- urllib子產品

urllib2(urllib.request)和urllib子產品的基本使用

注意: 在python3.3後urllib2已經不能再使用,隻能用urllib.request來代替

1.1 在python3中,urlopen預設是get請求

import urllib.request

#urlopen()函數,url是必須要傳入的,data如果傳入就是POST請求,如果不傳就是GETT請求
response = urllib.request.urlopen("https://www.baidu.com/")
#到伺服器傳回的資料,讀取裡面的全部内容
response_data = response.read()
#列印傳回的資料
print(response_data.decode("utf-8"))
           

下面是POST請求代碼

import urllib.request

#urlopen()函數,url是必須要傳入的,data如果傳入就是POST請求,如果不傳就是GETT請求
response = urllib.request.urlopen("http://www.baidu.com/", data="s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=尚矽谷".encode("utf-8"))
#到伺服器傳回的資料,讀取裡面的全部内容
response_data = response.read()
#列印傳回的資料
print(response_data.decode("utf-8"))
           

1.2. Request-封裝請求頭資訊

User-Agent 反爬蟲的第一步

在第一個例子裡,urlopen()的參數就是一個url位址;

但是如果需要執行更複雜的操作,比如增加HTTP報頭,必須建立一個 Request 執行個體來作為urlopen()的參數;而需要通路的url位址則作為 Request 執行個體的參數。

from urllib.request import Request,urlopen

header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
request = Request("http://www.baidu.com",headers=header)
#urlopen()函數,url是必須要傳入的,data如果傳入就是POST請求,如果不傳就是GETT請求
response = urlopen(request)
#到伺服器傳回的資料,讀取裡面的全部内容
response_data = response.read()
#列印傳回的資料
print(response_data.decode("utf-8"))
           

1.3 随機添加User-Agent

反爬蟲第二步

目的就是模拟不同的用戶端,讓伺服器以為是不同的使用者,不封ip

import random
from urllib.request import Request,urlopen

url = "http://www.atguigu.com"

ua_list = [
    "Mozilla/5.0 (Windows NT 6.1; ) Apple.... ",
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0)... ",
    "Mozilla/5.0 (Macintosh; U; PPC Mac OS X.... ",
    "Mozilla/5.0 (Macintosh; Intel Mac OS... "
]

user_agent = random.choice(ua_list)
#封裝請求資訊
request = Request(url)
#也可以通過調用Request.add_header() 添加/修改一個特定的header
request.add_header("User-Agent", user_agent)
# 第一個字母大寫,後面的全部小寫
request_info = request.get_header("User-agent")
print("request_info==",request_info)
#打開連接配接,請求資料
response = urlopen(request)
#把傳回的資料全部讀取完
html = response.read()
           

1.4 Url編碼後再請求路徑

from urllib import parse

if __name__ == "__main__":
   kw = input("請輸入你要爬取的貼吧名稱:")
   start_page = int(input("請輸入起始頁:"))
   end_page = int(input("請輸入結束頁面:"))
   kw = {"kw":kw}
   #轉換成url編碼
   kw = parse.urlencode(kw)
   url = "https://tieba.baidu.com/f?"
   url = url + kw
   print(url)
           

1.5 代碼通路帶有CA認證的網站

urllib.request在通路的時候則會報出SSLError

from urllib.request import Request,urlopen
# 1. 導入Python SSL處理子產品
import ssl
# 2. 表示忽略未經核實的SSL證書認證
context = ssl._create_unverified_context()
# 3.請求的路徑
url = "https://www.12306.cn/mormhweb/"
# 4.模拟浏覽器的請求頭資訊
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

# 5.傳入請求路徑和請求頭新
request = Request(url, headers = headers)
# 6. 發起請求,并且忽略ssl驗證
response = urlopen(request,context=context)

print(response.read().decode("utf-8"))
           

1.6. ProxyHandler處理器(代理設定)

使用代理IP(建議私密代理),這是爬蟲/反爬蟲的第三大招,通常也是最好用的。

· 西刺免費代理IP:http://www.xicidaili.com/

· 快代理免費代理:https://www.kuaidaili.com/free/inha/

· 全網代理IP:http://http.zhiliandaili.com/

from urllib.request import build_opener, ProxyHandler, Request

#建立私密代理處理對象(代理處理器)
proxy_hander = ProxyHandler({"http":"username:[email protected]:16819"})

#建立一個opper對象
opener = build_opener(proxy_hander)

#建立一個Request對象,并且把位址傳入
request = Request("http://www.baidu.com/")

#傳回響應資訊
reponse = opener.open(request)
#列印資訊
print(reponse.read().decode("utf-8"))
           

随機選擇ip:

from urllib.request import ProxyHandler,Request,build_opener
import random

#參數是字典類型,http是key,值是ip位址
#如果沒有代理的伺服器也要寫
proxy_list = [
    {"http" : "122.72.18.35:80"},
   {"http" : "122.72.18.34:80"},
   {"http" : "203.174.112.13:3128"},
]

# 随機選擇一個代理
proxy = random.choice(proxy_list)# 使用選擇的代理建構代理處理器對象
print(proxy)
http_proxyhander = ProxyHandler(proxy)

null_proxy_hander = ProxyHandler({})

proxy_switch = True
if proxy_switch:
   #傳回一個opener對象
   opener = build_opener(http_proxyhander)
else:
   opener = build_opener(null_proxy_hander)
#建構請求對象
request = Request("http://www.baidu.com/")
#傳回資料
response = opener.open(request)

#請求傳回到的資料
print(response.read())