初級爬蟲第二天
介紹了2種反爬的方式:
- 請求頭
- 代理IP
一、反爬手段1——向請求頭中添加User-Agent:
請求頭、響應頭:
1.響應頭:response_header
響應頭response_header,可以通過response對象.headers,獲取得到。
response.headers,得到的是響應頭信息
1 def load():
2 # 1.目標網頁URL地址
3 URL = "http://www.baidu.com/"
4
5 # 2.發送網絡請求:
6 # 返回response對象,使用response對象接收服務器返回的數據
7 response = urllib.request.urlopen(URL)
8
9 # 得到響應頭信息
10 print(response.headers)
11
12 load()
結果為:
1 Bdpagetype: 1
2 Bdqid: 0xbfd0e4790001890b
3 Cache-Control: private
4 Content-Type: text/html
5 Cxy_all: baidu+739fcb9dd92b830634cd2f957c8e6f67
6 Date: Fri, 03 May 2019 15:30:05 GMT
7 Expires: Fri, 03 May 2019 15:29:21 GMT
8 P3p: CP=" OTI DSP COR IVA OUR IND COM "
9 Server: BWS/1.1
10 Set-Cookie: BAIDUID=2D1BE12D094679CAE43187C509B76E5D:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
11 Set-Cookie: BIDUPSID=2D1BE12D094679CAE43187C509B76E5D; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
12 Set-Cookie: PSTM=1556897405; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
13 Set-Cookie: delPer=0; path=/; domain=.baidu.com
14 Set-Cookie: BDSVRTM=0; path=/
15 Set-Cookie: BD_HOME=0; path=/
16 Set-Cookie: H_PS_PSSID=28884_1454_21091_28724_28963_28837_28584; path=/; domain=.baidu.com
17 Vary: Accept-Encoding
18 X-Ua-Compatible: IE=Edge,chrome=1
19 Connection: close
20 Transfer-Encoding: chunked
和瀏覽器中f12,network中的Response Headers顯示的信息對比,基本一致
2.請求頭:request_header(重點)
User-Agent是在模擬真實用戶發送網絡請求
(1)目的:我們要向請求頭裏面,添加User-Agent信息,這樣就可以幹掉一部分的反爬手段。
(2)request = urllib.request.Request(目標網頁URL地址)
——創建request對象
要想獲取請求頭request_header,我們需要先創建request對象,然後通過request對象獲取請求頭。
註意:Request()首字母必須大寫
(3)request.headers,就可以得到請求頭的信息。
(4)request.add_header(‘User_Agent‘, ‘xxx‘)
——向請求頭中添加‘User-Agent’信息
使用爬蟲,最開始時,請求頭request_header中是空的,為了模擬真實用戶,需要向請求頭request_header中添加信息;必須先創建request對象之後,再向request_header中添加請求頭信息。
xxx就是冒號(:)後面的那些
(5)response = urllib.request.urlopen(request)
發送網絡請求,這個方法的參數,既可以是URL地址,也可以是request對象。
(6)request.get_header(‘User-agent‘)
——獲取請求頭信息的第二種方式
註意:
a. 這裏的參數是‘User-agent‘,只有U大寫,A小寫;
request.add_header()中,"User-Agent",U和A都大寫。
b. request.get_header(),這個方法只能得到請求頭的一部分信息
如:request.get_header(‘User-agent‘)只會得到User-Agent信息
而request.headers,得到的是請求頭的全部信息
(7)request.get_full_url()
可以得到完整的URL
(8)添加User-Agent信息,爬取百度首頁
1 import urllib.request
2 import urllib.parse
3
4 #爬取百度首頁https://www.baidu.com/
5 def load():
6 #1.目標網頁URL
7 URL = "https://www.baidu.com/"
8
9 #2.向請求頭中添加User-Agent信息
10 #2.1創建request對象,參數為目標網頁的URL
11 request = urllib.request.Request(URL)
12
13 #打印最開始時請求頭的User-Agent
14 print(request.get_header(‘User-agent‘))
15 #2.2向請求頭中添加User-Agent信息
16 request.add_headers(‘User-Agent‘, ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36‘)
17
18 #再次打印請求頭的User-Agent
19 print(request.get_header(‘User-agent‘))
20
21 #3.發送網絡請求,response接收返回數據
22 #參數填寫添加User-Agent信息之後的request對象
23 response = urllib.request.urlopen(request)
24
25 load()
結果:
可以看到,一開始時,User-Agent的信息為None,添加之後,為我們添加的信息
註意:發送網絡請求的代碼,urllib.request.urlopen(request)參數填寫request對象,而非URL;
如果填URL,則發送請求的請求頭沒有添加我們添加的User-Agent信息,還是為空None。
1.5 使用多個User-Agent:
(1)由於爬蟲會在極短的時間內(一秒鐘),訪問服務器很多次(幾百次)。所以,如果只使用一個User-Agent,很容易被服務器識別為爬蟲。
(2)反爬手段2.5:使用多個User-Agent
- 百度搜索:User-Agent大全
- 使用fake User-Agent(包含250個User-Agent)
- User-Agent池(推薦)
——這樣,每次發送網絡請求的瀏覽器信息和個人信息都不一樣,就可以幹掉反爬了
(3)思路:設置一個User-Agent的列表,每次從中隨機選取一個User-Agent
(4)代碼:
import urllib.request
import urllib.parse
import random
#爬取百度首頁https://www.baidu.com/
def load():
#1.目標網頁URL
URL = "https://www.baidu.com/"
#2.向請求頭中添加User-Agent信息
#2.1 設置User-Agent池:
user_agent_list = [‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60‘,
‘Opera/8.0 (Windows NT 5.1; U; en)‘,
‘Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50‘,
‘Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0‘,
‘Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10;‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60‘,
‘Opera/8.0 (Windows NT 5.1; U; en)‘,
‘Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50‘,
‘Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0‘,
‘Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36‘,
]
#2.2 從User-Agent池中隨機選擇一個User-Agent
choose_user_agent = random.choice(user_agent_list)
#2.2創建request對象,參數為目標網頁的URL
request = urllib.request.Request(URL)
#打印最開始時請求頭的User-Agent
print(request.get_header(‘User-agent‘))
#2.2向請求頭中添加User-Agent信息
request.add_headers(‘User-Agent‘, choose_user_agent)
#再次打印請求頭的User-Agent
print(request.get_header(‘User-agent‘))
#3.發送網絡請求,response接收返回數據
#參數填寫添加User-Agent信息之後的request對象
response = urllib.request.urlopen(request)
load()
二、反爬手段2——代理IP:
理論:
(1)IP分為免費IP和付費IP:
1.1 免費IP:時效性差,錯誤率高
1.2 付費IP:時效性強,錯誤率低,但是也有失效的IP
(2)IP的三種叫法:
2.1 透明IP:對方知道我自己的真實IP
2.2 匿名IP:對方不知道我自己的真實IP,但是知道我使用了代理IP
2.3 高匿名IP:對方不知道我自己的真實IP,也不知道我使用了代理IP
註:由圖可以發現,代理IP分為HTTP和HTTPS,可以根據自己的需求,找自己要的類型IP
(3)IP分為免費IP寫法和付費IP寫法
(4)發送網絡請求,需要使用我們自己添加的代理IP。看上面的爬蟲代碼,可以發現:在發送網絡請求之前,只涉及到兩個東西,一個是request對象、另一個是urllib.request.urlopen()方法。
查看request和urlopen()
通過查看request對象和urlopen()方法源碼,發現這兩個對象,都沒有提供加入代理IP的位置。
所以,我們應該在哪裏加入,我們自己想要偽裝的代理IP呢???
查看urlopen()方法代碼
發現:該方法的本質是創建了一個opener對象,返回的是opener.open()
而opener對象,又是通過build_opener()一個handler處理器對象得來的
所以說,如果能在handler對象中加入我們要偽裝的代理IP,然後用該對象創建opener對象,再調用open()方法,就可以達到我們的目的:偽裝使用代理IP向服務器發送網絡請求。
總結一下:
- urlopen()和request對象都沒有添加IP的方法
- urlopen()的底層本質上是:先創建handler對象,然後創建opener對象,再用opener.open()的方法發送網絡請求,爬取數據。
- 我們需要創建一個能夠添加代理IP的handler處理器——proxyhandler,然後利用它創建opener對象,最後發送請求。
代碼:
import urllib.request
import urllib.parse
import string
import random
# 使用添加的User-Agent和代理IP,爬取搜狗搜索的首頁
def load():
# 1.目標網頁URL:
URL = ‘https://www.sogou.com/‘
# 2.向請求頭添加User-Agent
# 2.1創建request對象
request = urllib.request.Request(URL)
# 2.2設置User-Agent池
User_Agent_List = [
‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60‘,
‘Opera/8.0 (Windows NT 5.1; U; en)‘,
‘Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50‘,
‘Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0‘,
‘Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10;‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60‘,
‘Opera/8.0 (Windows NT 5.1; U; en)‘,
‘Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50‘,
‘Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0‘,
‘Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2‘,
‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36‘,
]
# 2.3每次請求隨機選擇一個User-Agent
choose_User_Agent = random.choice(User_Agent_List)
# 2.4向請求頭信息中,添加User-Agent
request.add_header(‘User-Agent‘, choose_User_Agent)
# 3.添加代理IP
# 3.1設置代理IP
proxy_ip = {‘https‘: ‘116.52.13.90:808‘}
# 3.2創建handler處理器對象
proxy_handler = urllib.request.ProxyHandler(proxy_ip)
# 3.3創建opener對象(因為真正發送網絡請求的是opener而非handler)
opener = urllib.request.build_opener(proxy_handler)
# 3.4調用open方法,發送網絡請求
response = opener.open(request)
# 4.發送網絡請求,使用response對象接收數據
#因為3.4中已經做了
# 5.讀取response對象裏面的數據,轉碼為字符串格式
str_data = response.read().decode(‘utf-8‘)
# 6.保存數據
with open(‘sougou.com02.html‘, ‘w‘, encoding=‘utf-8‘) as f:
f.write(str_data)
load()
註意:
(1)代理IP的設置格式:
1.1 使用字典放置
1.2 鍵key:相應的代理IP的類型(http或者https)
1.3 值value:代理IP:端口號
1.4 鍵http/https;值IP地址+端口號,均使用字符串格式
eg:
proxy = {‘http‘: "115.223.69.54:8010", "https": "116.209.52.248:9999"}
(2)opener.open()中的參數,既可以是目標網頁的URL也可以是request對象。這裏由於,我們要使用添加的User-Agent,所以參數用request對象。
初級爬蟲第二天