python爬蟲(5)——正則表達式(二)
前一篇文章,我們使用re模塊來匹配了一個長的字符串其中的部分內容。下面我們接著來作匹配“[email protected] advantage 314159265358 1892673 3.14 little Girl try_your_best 56 [email protected] python3”
我們的目標是匹配‘56’,其中\d表示匹配數字,{2}表示匹配次數為兩次,{M,N},M,N均為非負整數,M<=N,表示匹配M-N次。在匹配規則前面加個r的意思是表示原生字符串。
實際上我們在使用正則表達式的時候,通常先將其編譯成pattern對象,使用re.compile()方法來進行編譯。下面我們來匹配IP地址如:192.168.1.1。
1 import re 2 3 str=‘192.168.1.1‘ 4 5 re.search(r‘(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])‘,str)
可以看出來,正則使用起來並不簡單。在上面的規則中,我們是用了三個子組,如果我們在網頁上用findall匹配所有IP,它會把結果給分類了,變成(‘192’,‘168’,‘1’,‘1’)。顯然這不是我們想要的。這時候,我們需要用(?:...)來表示非捕獲組,即該子組匹配的字符串無法從後面獲取。
有了之前的基礎,我嘗試著寫下了如下的代碼,從西刺代理網站上爬取IP地址,並用代理訪問網站驗證其是否可用。當中用到了python的異常處理機制。雖然代碼不成熟,但還是分享出來,慢慢改進。
1 import urllib.request 2 import re 3 4 5 url="http://www.xicidaili.com/" 6 useful_ip=[] 7 def loadPage(url): 8 headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"} 9 response=urllib.request.Request(url,headers=headers)10 html=urllib.request.urlopen(response).read().decode("utf-8") 11 return html 12 13 def getProxy(): 14 html=loadPage(url) 15 pattern=re.compile(r‘(<td>\d+</td>)‘) 16 duankou=pattern.findall(html) 17 pattern=re.compile(r‘(?:(?:[01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}(?:[01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])‘) 18 content_list=pattern.findall(html) 19 list_num=[] 20 for num in duankou: 21 list_num.append(num[4:-5]) 22 for i in range(len(list_num)): 23 ip=content_list[i]+ ":"+list_num[i] 24 while True: 25 proxy_support=urllib.request.ProxyHandler({‘http‘:ip}) 26 opener=urllib.request.build_opener(proxy_support) 27 opener.add_handler=[("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36")] 28 urllib.request.install_opener(opener) 29 try: 30 print("正在嘗試使用 %s 訪問..." % ip) 31 ip_filter="http://www.whatsmyip.org/" 32 ip_response=urllib.request.urlopen(ip_filter) 33 except urllib.error.URLError: 34 print("訪問出錯,這個IP不能用啦") 35 break 36 else: 37 print("訪問成功!") 38 print("可用IP為: %s " % ip) 39 useful_ip.append(ip) 40 if input("繼續爬取?")=="N": 41 print("有效IP如下:") 42 for key in useful_ip: 43 print(key) 44 exit() 45 else: 46 break 47 48 if __name__=="__main__": 49 getProxy()
在處理IP地址對應的端口號時,我用的一個非常笨的方法。實際上有更好的辦法解決,大家也可以想一想。在上面這段代碼中,使用urllib訪問網站、Handler處理器自定義opener、python異常處理、正則匹配ip等一系列的知識點。任何知識,用多了才會熟練。
可以看到它運行成功,並且找到一個可用IP後會問你是否繼續爬取。當然,我們可以手動構建一個IPPOOL即IP池,自定義一個函數,把可以用的IP寫入一個文件保存起來,這裏就不作贅述了。在github上有成熟的ip池代碼,大家可以下載下來閱讀,這裏只是把前面講的一些用法做一個簡單的試驗,因此並沒有把這段代碼完善。
python爬蟲(5)——正則表達式(二)