Handler和Opener
Handler處理器和自定義Opener
opener是urllib2.OpenerDirector的實例,我們之前一直在使用urlopen,它是一個特殊的opener(也就是我們構建好的)。
但是urlopen()方法不支持代理、cookie等其他的HTTP/GTTPS高級功能。所有要支持這些功能:
1.使用相關的Handler處理器來創建特定功能的處理器對象;
2.然後通過urllib2.build_opener()方法使用這些處理器對象,創建自定義opener對象;
3.使用自定義的opener對象,調用open()方法發送請求。
如果程序裏所有的請求都使用自定義的opener,可以使用urllib2.install_open()將自定義的opener對象定義爲全局opener,表示如果之後凡是調用urlopen,都將使用這個opener(根據自己的需求來選擇)
自定義opener()
# _*_ coding:utf-8 _*_
import urllib2
# 構建一個HTTPHandler處理器對象,支持處理HTTP的請求
http_handler = urllib2.HTTPHandler()
# 調用build_opener()方法構建一個自定義的opener對象,參數是構建的處理器對象
opener = urllib2.build_opener(http_handler)
request = urllib2.Request('http://www.139.com')
# 調用自定義opener對象的open()方法,發送request請求
response = opener.open(request)
print response.read()
設置代理IP
很多網站會檢測某一段時間某個IP的訪問次數(通過流量統計,系統日誌等),如果訪問次數多的不像正常人,它會禁止這個IP的訪問。
所以我們可以設置一些代理服務器,每隔一段時間換一個代理,就算IP被禁止,依然可以換個IP繼續爬取。
urllib2中通過ProxyHandler來設置使用代理服務器,使用自定義opener來使用代理:
代理IP網站:http://www.xicidaili.com/;https://www.kuaidaili.com/free/inha/
# _*_ coding:utf-8 _*_
import urllib2
# 構建一個Handler處理器對象,參數是一個字典類型,包括代理類型和代理服務器IP+Port
httpproxy_handler = urllib2.ProxyHandler({'http':'118.114.77.47:8080'})
#使用代理
opener = urllib2.build_opener(httpproxy_handler)
request = urllib2.Request('http://www.baidu.com/s')
#1 如果這麼寫,只有使用opener.open()方法發送請求才使用自定義的代理,而urlopen()則不使用自定義代理。
response = opener.open(request)
#12如果這麼寫,就是將opener應用到全局,之後所有的,不管是opener.open()還是urlopen() 發送請求,都將使用自定義代理。
#urllib2.install_opener(opener)
#response = urllib2.urlopen(request)
print response.read()
示例
#coding=utf-8
import urllib2
import re
import xlwt
import smtplib
import random
import time
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
# 1.先獲取整個頁面信息
# Urllib 模塊提供了讀取web頁面數據的接口,我們可以像讀取本地文件一樣讀取www和ftp上的數據。
# 首先,我們定義了一個getHtml()函數:
# urllib.urlopen()方法用於打開一個URL地址。
# read()方法用於讀取URL上的數據,向getHtml()函數傳遞一個網址,並把整個頁面下載下來。執行程序就會把整個網頁打印輸出。
#
# #添加頭部header
# Agent_list = [ ]
# user_agent = random.choice(Agent_list)
# page.add_header('User-Agent',user_agent)
#
#
# #定義opener,設置代理IP
# ip_list = []
# httpproxy_handler = urllib2.ProxyHandler({'http':random.choice(ip_list)})
# opener = urllib2.build_opener(httpproxy_handler)
# urllib2.install_opener(opener)
def getHtml(url):
Agent_list = ['Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36',
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11"
]
ip_list = ['223.198.16.58:9999','110.244.12.96:9999','61.145.8.103:9999','223.198.19.214:9999','112.85.125.111:9999']
user_agent = random.choice(Agent_list)
httpproxy_handler = urllib2.ProxyHandler({'http':random.choice(ip_list)})
opener = urllib2.build_opener(httpproxy_handler)
urllib2.install_opener(opener)
page = urllib2.Request(url)
page.add_header('User-Agent',user_agent)
response = urllib2.urlopen(page)
html = response.read()
return html
# 2.篩選頁面中想要的數據
# 我們又創建了geturl()函數,用於在獲取的整個頁面中篩選需要的視頻連接。
# re模塊主要包含了正則表達式:
# r"<a href='(/html/gndy/+.+html)'",表示查找類似/html/gndy/jddy/20190607/58704.html地址的超鏈接。
# 正則表達式輸出的是括號()裏面的內容。
#
# 正則表達式示例:r'(.*) are (.*?) .*'
# 首先,這是一個字符串,前面的一個 r 表示字符串爲非轉義的原始字符串,讓編譯器忽略反斜槓,也就是忽略轉義字符。
# 但是這個字符串裏沒有反斜槓,所以這個 r 可有可無。
# . :匹配一個除了換行符任意一個字符
# ^ :只有後面跟的字符串在開頭,才能匹配上
# * :它控制它前面那個字符,他前面那個字符出現0到多個都可以匹配上
# + :匹配前面那個字符1到多次
# ?:匹配前面那個字符0到1個,多餘的只匹配一個
# (.*) 第一個匹配分組,.* 代表匹配除換行符之外的所有字符。
# (.*?) 第二個匹配分組,.*? 後面多個問號,代表非貪婪模式,也就是說只匹配符合條件的最少字符
# 後面的一個 .* 沒有括號包圍,所以不是分組,匹配效果和第一個一樣,但是不計入匹配結果中。
#
# re.search("com","COM",re.I).group()
# re.I 使匹配對大小寫不敏感
# re.L 做本地化識別(locale-aware)匹配
# re.M 多行匹配,影響^和$
# re.S 使.匹配包括換行在內的所有字符
#
# <a href="">..</a>表示超鏈接
# re.compile() 可以把正則表達式編譯成一個正則表達式對象.
# re.findall() 方法讀取html 中包含 urlre(正則表達式)的數據。
# 運行腳本將得到整個頁面中包含圖片的URL地址。
#
# reg = r"<a href='(/html/gndy/.*)</a><br/>"
# 匹配類似<a href='/html/gndy/jddy/20160320/50523.html'>IMDB評分8分左右影片400餘部</a><br/> 並輸出括號裏面的內容
# 得到 /html/gndy/jddy/20160320/50523.html'>IMDB評分8分左右影片400餘部
# 可以用 reg = r"<a href='(/html/gndy/.*?)</a><br/>"
# 可以用 reg = r"<a href='(/html/gndy/.+)</a><br/>"
# 可以用 reg = r"<a href='(/html/gndy/.+?)</a><br/>"
#
# re.split(r"'>+",resource_url) 將得到的結果‘/html/gndy/jddy/20160320/50523.html'>IMDB評分8分左右影片400餘部’ 按照‘>切割成兩部分。
# down_addr = '' + down_page[j] down_page無法顯示漢字,所以做了下轉化
#
# for i in range (1,20) 查詢需要的條記錄,從1開始的原因是因爲第0個記錄不是需要的數據。
def geturl(html):
reg = r"<a href='(/html/gndy/.*)</a><br/>"
urlre = re.compile(reg)
urllist = re.findall(urlre,html)
wbk = xlwt.Workbook(encoding='gbk')
worksheet = wbk.add_sheet('My worksheet')
list1=('Name','Page','Url')
for i in range(1,20):
resource_url = "https://dytt8.net" + urllist[i]
result = re.split(r"'>+",resource_url)
Agent_list = ['Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36',
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]
ip_list = ['223.198.16.58:9999','110.244.12.96:9999','61.145.8.103:9999','223.198.19.214:9999','112.85.125.111:9999']
user_agent = random.choice(Agent_list)
httpproxy_handler = urllib2.ProxyHandler({'http':random.choice(ip_list)})
opener = urllib2.build_opener(httpproxy_handler)
urllib2.install_opener(opener)
user_agent = random.choice(Agent_list)
down_page = urllib2.Request(result[0])
down_page.add_header('User-Agent',user_agent)
print down_page.get_header('User-agent')
response_page = urllib2.urlopen(down_page)
down_html = response_page.read()
addr_code = r'<a href="(ftp://.*)">'
addr_re = re.compile(addr_code)
down_url = re.findall(addr_re,down_html)
down_addr = '' + down_url[0]
if i == 1:
for list in range(0,len(list1)):
worksheet.write(i-1,list,list1[list])
else:
worksheet.write(i-1,0,result[1])
worksheet.write(i-1,1,result[0])
worksheet.write(i-1,2,down_addr)
time.sleep(5)
wbk.save('renew.xls')
#3. 發送郵件
def send_mail():
user = 'xxxx.com'
pwd = 'xxxxs'
to = 'xxxx'
msg = MIMEMultipart()
msg["Subject"] = '電影記錄'
msg ["From"] = user
msg ["To"] = to
part1 = MIMEText("你好,\n\n 電影記錄見附件。")
msg.attach(part1)
part2 = MIMEApplication (open(r'E:\2xx3\python腳本\html\renew.xls','rb').read())
part2.add_header('Content-Disposition','attachment',filename='renew.xls')
msg.attach(part2)
s = smtplib.SMTP("smtp.139.com",timeout=30)
s.login(user,pwd)
s.sendmail(user,to,msg.as_string())
s.close()
html = getHtml("https://www.dytt8.net/index0.html")
geturl(html)
send_mail()