1. 程式人生 > >tensorflow入門教程(十七)python3網路爬蟲(上)

tensorflow入門教程(十七)python3網路爬蟲(上)

1、概述

在繼續學習tensorflow之前,我想先寫一下python爬蟲的內容,作為深度學習的一個技能補充。深度學習需要用到大量的訓練資料,沒有爬蟲靠人工下載,工作量不敢想象。學會爬蟲就可以去爬一些收集訓練資料需要(或喜歡)的網站了。如果想深入學習爬蟲,推薦這本書《精通Python網路爬蟲+核心技術、框架與專案實戰》,下載連結為:

1、Urllib庫

Urllib庫是python的一個用於操作URL的庫,Python2.X中分為Urllib庫和Urllib2庫,Python3.X之後將其合併到Urllib庫。這一節用的是Python3.5.

2.1、使用Urllib爬取網頁

使用Urllib爬取網頁很簡單,首先匯入Urllib模組,

import urllib.request as ur

然後用urllib.request.urlopen開啟並爬取一個網頁,

urlfile = ur.urlopen("http://www.baidu.com")

再用read將網頁內容讀取出來,然後,列印看看,

data = urlfile.read()
print(data)

執行結果:

當然也可以用readline函式只讀取一行的內容,就不演示了。

如果想將爬取的網頁儲存到本地檔案,那麼先open一個本地檔案,再write資料,最後close關閉檔案即可,程式碼如下。

fd = open("baidu.html", "wb")
fd.write(data)
fd.close()

執行以後,發現本地多了個baidu.html檔案,用瀏覽器執行,得到介面如下,

就這麼簡單的將百度首頁爬取到了本地,只是沒將圖片爬取到本地而已。

Urllib庫還提供了一個直接將網頁寫入本地檔案的方法urllib.request.urlretrieve函式,程式碼如下:

ur.urlretrieve("https://blog.csdn.net/rookie_wei",filename="rookie_wei.html")

Urllib的其他用法這裡就不一一介紹了,自己百度吧。

2.2、模擬瀏覽器訪問

如果只用上面的方法去訪問網頁,有些網頁為了防止惡意爬蟲會進行一些反爬蟲設定,就會返回403錯誤。為了避免這個錯誤,我們可以設定一些Headers資訊,模擬成瀏覽器去訪問這些網站。

開啟瀏覽器的開發者工具(F12鍵),點選“Network”,

然後開啟任意網站(比如百度),可以看到工具窗口出現一些資料,

點選任意一個數據,看到右邊出現一個視窗,Headers標籤就是頭資訊,將右邊視窗往下滾動,可以找到“User-Agent”標籤,

這個就是模擬瀏覽器訪問需要用到的資訊,將其複製下來,得到資訊:Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0

可以用兩種方法將我們的爬蟲模擬成瀏覽器訪問。

方法一:使用build_opener()修改報頭

urlopen不支援一些HTTP高階功能,可以使用urllib.request.build_opener,程式碼如下,

#encoding:utf-8
import urllib.request as ur
url = "https://blog.csdn.net/rookie_wei"
headers = ("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0")
opener = ur.build_opener()
opener.addheaders = [headers]
data = opener.open(url).read()
print(data)

執行結果跟上面的一樣。

方法二:使用add_header()新增報頭

直接上程式碼,

#encoding:utf-8
import urllib.request as ur
url = "https://blog.csdn.net/rookie_wei"
req = ur.Request(url)
req.add_header("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0")

data = ur.urlopen(req).read()
print(data)

執行結果跟上面的一樣。

2.3、設定超時時間

有時候訪問一個網頁,如果網頁長時間未相應,那麼系統就會判斷該網頁超時,即無法開啟網頁。有時候我們需要自己設定超時的時間值,方法很簡單,在使用urlopen時,設定timeout的值即可,單位是秒。例如,

urlfile = ur.urlopen("https://blog.csdn.net/rookie_wei", timeout=30)

2.4、使用代理伺服器

有時候使用同一個IP高頻地去爬取同一個網站,久了之後,可能會被網站的伺服器遮蔽,解決這個問題的方法就是使用代理伺服器去訪問。使用代理伺服器去爬取網站時,對方網站顯示的是代理伺服器的IP地址,即使這個地址被遮蔽了,我們換個代理就是了。

下面的網站提供了很多代理伺服器的地址,

有了代理伺服器,下面就可以上示例程式碼了,

#encoding:utf-8
import urllib.request as ur

def use_proxy(proxy_addr, url):
    proxy = ur.ProxyHandler({'http':proxy_addr})
    opener = ur.build_opener(proxy, ur.HTTPHandler)
    ur.install_opener(opener)
    data = ur.urlopen(url, timeout=30).read().decode('utf-8')
    return data

proxy_addr = '121.196.218.197:3128'
data = use_proxy(proxy_addr, 'https://blog.csdn.net/rookie_wei')
print(data)

如果有些代理不能用了,換一個就是了。

2.5、異常處理

程式在執行過程中難免發生異常,如果不處理,有可能導致整個程式異常退出。python的異常處理也是使用try...except語句,在try中執行主要程式碼,在except中捕獲異常資訊,並進行相應處理。這個比較簡單,我就不詳細講了,但是這個內容還是很重要的,直接上個例子吧。

#encoding:utf-8
import urllib.request as ur
import urllib.error as ue
try:
    ur.urlopen('https://blog.csdn.net/rookie_weia')
except ue.URLError as e:
    print('我出現異常啦!')
    print(e.code)
    print(e.reason)

執行結果:

我故意訪問一個不存在的網址,可以看到發生異常後,程式會執行except裡的程式碼。

3、正則表示式

正則表示式在爬蟲中很重要。正則表示式就是描述字串排列的一套規則,比如,我們想找出一個網頁中所有圖片,其他的資訊過濾掉,那麼就觀察圖片的格式,然後寫一個正則表示式來表示所有的圖片,等等。

3.1、原子:

原子是正則表示式最基本的組成單元,每個正則表示式中至少要包含一個原子。常見的原子分為普通字元作為原子、非列印字元作為原子、通用字元作為原子、原子表。下面就來分別講解。

(1)普通字元作為原子

普通字元,即數字、大小寫字母、下劃線等,例如將”wei”作為原子使用,這這裡有三個原子,分別是”w”、”e”、”i”,舉個示例。程式碼如下,

import re
pattern = 'wei'
str = '_wei'
result = re.search(pattern, str)
print(result)

執行結果:

python中使用正則表示式需要用到re模組,pattern變數定義了正則表示式的值,然後使用re模組的search函式在str字串裡匹配對應的正則表示式,然後將結果返回給變數result。從列印結果可以看出,span表示匹配的位置,match表示匹配結果。如果匹配失敗,則返回None,可以將字串改為str = '_wedi'輸出結果為,

(2)非列印字元作為原子

非列印字元作為原子指的是一些在字串中用於格式控制的符號,如換行符”\n”等。

(3)通用字元作為原子

通用字元作為原子,即一個原子可以匹配一類字元。常見通用字元及其含義如下表所示,

例如,我們可以使用”\w\dwei\w”對”wei”字元匹配,則“12weia”、“w2wei_”都可以匹配成功。

(4)原子表

原子表可以定義一組地位平等的原子,然後匹配時會取該原子表中任意一個原子進行匹配,python中原子表用[]表示,例如[abc]就是一個原子表,假設我們定義正則表示式為”[abc]wei”,源字串為”cweifang”,則用re.search函式匹配,匹配的結果就是“cwei”。如果源字串為”wei”,則不匹配,返回None。

[^]則表示除了括號內的原子以外,都可以匹配,比如定義正則表示式為”[^abc]wei”,源字串為”cweifang”,則不匹配,源字串為”zwei”則匹配。

3.2、元字元

元字元,就是正則表示式中具有一些特殊含義的字元,比如重複N此前面的字元等,常見元字元如下表所示,

3.3、模式修正

模式修正,即可以在不改變正則表示式的情況下,通過模式修正符改變正則表示式的含義,從而實現一些匹配結果的調整等功能。

舉個例子,

import re
pattern1 = 'wei'
pattern2 = 'wei'

str = 'ahWeiqew'

print(re.search(pattern1, str))
print(re.search(pattern2, str, re.I))

執行結果:

3.4、正則表示式常見函式

re.match函式:

該函式從源字串的起始位置匹配一個模式,函式的格式為,

re.match(pattern, string, flags=0)

第一個引數是表示式,第二個引數是源字元,第三個引數是可選引數,代表對應的標誌位,可以放模式修正等資訊。示例程式碼如下,

import re
pattern1 = '.wei'
str = 'aWeiqew'
print(re.match(pattern1, str, re.I))

執行結果:

re.search函式:

re.search函式會掃描整個字串進行匹配,而re.match函式從字串開頭進行匹配,它們用法是一樣的。

re.compile和findall函式

前面介紹的兩個函式,即使源字串中含有多個匹配結果,也只會返回一個,而re.compile函式和findall函式的組合使用則可以將符合模式的內容全部匹配出來。示例程式碼如下,

import re

str = 'aWeiqew8732weiadnwei2103_wei'
pattern = re.compile('.wei.')
print(pattern.findall(str))

執行結果:

4、多執行緒

使用多執行緒會使爬蟲效率大大提高,比如在爬取圖片的爬蟲中,開啟一個執行緒獲取圖片的url地址,一個執行緒進行下載,則比單個執行緒先獲取圖片url再下載的效率高很多。這裡就簡單介紹python的多執行緒。

import threading

class A(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        for i in range(1000):
            print('我是執行緒A')


class B(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        for i in range(1000):
            print('我是執行緒B')

t1 = A()
t1.start()

t2 = B()
t2.start()

執行結果:

總結:

這一節就先學習爬蟲的一些最基本的知識,如果想深入學習的話,推薦我在概述裡給的那本書。我的目的不是成為爬蟲高手,只要滿足爬取我需要的訓練資料即可。講了這麼多屁話有什麼用?下一節就來兩個真實的爬蟲示例,一個是爬取汽車之家的汽車廠商及車型,還有一個是在爬取百度圖片中爬取我們想搜尋的圖片。學完之後,就可以爬一些喜歡的小網站的圖片和視訊了。