Python爬蟲實戰---抓取圖書館借閱資訊,python爬蟲

來源:互聯網
上載者:User

Python爬蟲實戰---抓取圖書館借閱資訊,python爬蟲

Python爬蟲實戰---抓取圖書館借閱資訊

原創作品,引用請表明出處:Python爬蟲實戰---抓取圖書館借閱資訊 

 

  前段時間在圖書館借了很多書,借得多了就容易忘記每本書的應還日期,老是擔心自己會違約,影響日後借書,而自己又懶得總是登入到學校圖書館借閱系統查看,於是就打算寫一個爬蟲來抓取自己的借閱資訊,把每本書的應還日期給爬下來,並寫入txt檔案,這樣每次忘了就可以開啟該txt檔案查看,每次借閱資訊改變了,只要再重新運行一遍該程式,原txt檔案就會被新檔案覆蓋,裡面的內容得到更新。

用到的技術:  

  Python版本是 2.7 ,同時用到了urllib2、cookielib、re三個模組。urllib2用於建立請求(request),並抓取網頁資訊,返回一個類似於檔案類型的response對象;cookielib用於儲存cookie對象,以實現類比登入功能;re模組提供對Regex的支援,用於對抓取到的頁面資訊進行匹配,以得到自己想要的資訊

抓取一個頁面:  

  使用urllib2簡單抓取一個網頁的過程非常簡單:

1 import urllib22 response = urllib2.urlopen("http://www.baidu.com")3 html = response.read()

   urllib2中的urlopen()方法,看其字面意思就知道是開啟一個URL(uniform resource locator)地址,上面例子傳入的時百度首頁的地址,遵循HTTP協議,除了http協議外,urlopen()方法還可以開啟遵循ftp、file協議的地址,如:

1 response = urllib2.urlopen("ftp://example.com")

  除URL參數外,urlopen()方法還接受data和timeout參數:

1 response = urllib2.urlopen(url ,data ,timeout)

  其中data是開啟一個網頁時需要傳入的資料,比如開啟一個登入介面時往往需要傳入使用者名稱和密碼等資訊,在下文登入圖書館系統時將會看到其用法;timeout是設定逾時時間,即超過一定時間頁面無響應即報錯;在urlopen()方法中,data和timeout不是必須的,即可填可不填,注意:當頁面需要有資料傳入時,data是必需的。

  可以看到,在開啟一個網頁時,有時往往需要傳入多個參數,再加上HTTP協議是基於請求(request)和應答(response)的,即用戶端發出請求(request),伺服器端返回應答(response),所以在使用urlopen()方法時,往往是構造一個request對象作為參數傳入,該request對象包括url、data、timeout、headers等資訊:

1 import urllib22 request = urllib2.Request("http://www.baidu.com")3 response = urllib2.urlopen(request)4 html = response.read()

  這段代碼得到的結果和上面得到的結果一樣,但是在邏輯上顯得更明確、清晰。

Cookie的使用:  

  在訪問某些網站時,該網站需要在用戶端本地儲存一些資料、資訊(經過加密),並在接下來的請求(request)中返回給伺服器,否則伺服器將拒絕該請求,這些資料即儲存在本地的cookie中。例如,訪問學校圖書館系統時,需進行登入,等登入完成之後,伺服器端將會在本地儲存一些經過加密的資料在cookie中,當用戶端發送查詢借閱資訊的請求(request)時,會連帶cookie裡面的資料一起發送給伺服器,伺服器確定cookie資訊後允許訪問,否則拒絕該請求。

  Cookielib模組提供了CookieJar類用於捕捉和儲存HTTP 的cookie資料,所以要建立一個cookie只要建立一個CookieJar執行個體即可:

1 import cookielib2 cookie = coolielib.CookieJar()

   建立cookie了就萬事大吉了嗎?沒那麼簡單,我們要完成的操作是發送登入請求、記錄cookie、再發送讀取借閱資訊的請求並向伺服器反饋cookie資訊,要完成這一系列的操作,原來的urlopen()方法已不能勝任,幸運的是,urllib2模組還提供了一個OpenerDirector類,可以接受一個cookie處理器為參數,實現上述功能,而這個cookie處理器則可以通過HTTPCookieProcessor類接受一個cookie對象執行個體化後得到。即先通過HTTPCookieProcessor執行個體化得到一個cookie處理器handler,再將此處理器headler作為參數傳入OpenDirector執行個體化得到一個能捕捉cookie資料的opener,代碼如下:

1 import urllib22 import cookielib3 4 cookie = cookielib.CookieJar()5 handler = urllib2.HTTPCookieProcessor(cookie)6 opener = urllib2.build_opener(handler)7 response = opener.open("http://www.baidu.com")

 登入圖書館系統:

  至此,我們就可以進行圖書館借閱資訊的抓取了。來看看hit圖書館登入介面:

                                       

  首先,在Firefox瀏覽器下,藉助httpfox外掛程式進行網路監聽,看看登入此頁面需要向伺服器發送哪些資料:

                                                 

  輸入登入帳號和密碼,開啟httpfox外掛程式,點擊start開始監聽,然後點擊登陸按鈕進行登陸:

                                                  

  便是登陸之後的頁面,以及整個登陸過程捕捉到的資訊。選擇第一條捕捉到的資訊,點擊下方資料頭(Headers)選項卡,可以看見登入此頁面需要發送的一些資料。有一些網站,對於訪問它們的請求需要檢查資料頭(Headers),只有資料頭資訊符合要求才允許訪問。在登入圖書館系統時,可以先嘗試不發資料頭,如果能順利訪問則說明沒有Headers檢查這一環節。資料發送的方法為GET,即只需要將要發送的資料資訊加在登陸請求的後面。在Headers選項卡的Request-Line屬性中,問號前面的即為登陸請求"GET /lib/opacAction.do",加上IP地址之後真實的請求URL為"http://202.118.250.131/lib/opacAction.do",問號後面的即為登陸需要的資料,包括帳號、密碼等資訊。

  接下來點開QueryString選項卡,查看由GET方法傳送的資料:

             

  需要傳送的資料包括5項,以字典類型將其儲存,經過urlencode()方法編碼之後直接加在登陸URL之後即可,所以最後向伺服器發送的請求(request)為:

 1 import urllib 2  3 loginURL = 'http://202.118.250.131/lib/opacAction.do' 4 queryString = urllib.urlencode({ 5             'method':'DoAjax', 6             'dispatch':'login', 7             'registerName':'', 8             'rcardNo':'16S137028 0', 9             'pwd':'******'10         })11 requestURL = self.loginURL + '?' + self.queryString

  得到請求URL之後就可以類比登陸圖書館系統了,在類比登陸的過程中需要用到前面講到的cookie,否則無法進行後續的訪問。在編代碼過程中,定義一個library類,使訪問過程變成一個物件導向的過程,可以根據需要執行個體化多個library對象,分別對多個執行個體進行操作。首先分析,該library類應該有一個初始化方法(__init__)以及一個擷取頁面的方法(getPage),在開啟網頁是,應使用上文提到opener執行個體,自動捕獲並儲存cookie:

 

 1 import urllib 2 import urllib2 3 import cookielib 4 import re 5  6 class library: 7     def __init__(self): 8         self.loginURL='http://202.118.250.131/lib/opacAction.do' 9         self.queryString = urllib.urlencode({10             'method':'DoAjax',11             'dispatch':'login',12             'registerName':'',13             'rcardNo':'16S137028 0',14             'pwd':'114477yan'15         })16         self.requestURL = self.loginURL + '?' + self.queryString17         self.cookies=cookielib.CookieJar()18         self.handler=urllib2.HTTPCookieProcessor(self.cookies)19         self.opener=urllib2.build_opener(self.handler)20     def getPage(self):21         request1 = urllib2.Request(self.requestURL)22         request2 = urllib2.Request(' http://202.118.250.131/lib/opacAction.do?method=init&seq=301 ')23         result = self.opener.open(request1)24         result = self.opener.open(request2)25         return result.read()26 27 lib = library()28 print lib.getPage()

 

  上述代碼中,先是進行登入 result = self.opener.open(request1) ,登入沒有異常,說明登入過程不用檢查資料頭;然後再用此 self.opener 開啟借閱查詢頁面
 http://202.118.250.131/lib/opacAction.do?method=init&seq=301 ,所以這段代碼將列印借閱查詢介面的HTML代碼,是部分列印結果:

                

擷取借閱資訊:

  抓取了頁面資訊之後,接下來就是根據自己的需要匹配、儲存資訊了。在匹配頁面資訊時,這裡用的是Regex的方式進行匹配,Regex的支援由Python的Re模組提供支援,關於如何使用Regex,可以參考這裡:PythonRegex指南

  使用Re模組進行匹配時,往往先將Regex字串編譯(compile)成一個Pattern執行個體,再利用Re模組中的re.findall(pattern , string),將字串string中和Regex匹配的資料以列表的形式返回。如果在pattern中有超過一個組(group),則返回的結果將是一個元組列表,如此Regex: <table.*?id="tb.*?width="50%"><font size=2>(.*?)</font>.*?<tr>.*?<tr>.*?<font size=2>(.*?)</font>.*?<font size=2>(.*?)</font>.*?</TABLE> ,式中,每一個 (.*?) 代表一個組,即此式中有3個組,則匹配時,返回一個元組列表,其中每一個元組又有3個資料。

  在library類中,定義一個擷取資訊的方法(getInformation),以通過Regex匹配的方式擷取所需資料:

1 def getInformation(self):2         page = self.getPage()3         pattern = re.compile('<table.*?id="tb.*?width="50%"><font size=2>(.*?)</font>.*?<tr>.*?<tr>.*?'+4                         '<font size=2>(.*?)</font>.*?<font size=2>(.*?)</font>.*?</TABLE>',re.S)5         items = re.findall(pattern,page)

  擷取所需資料之後,接下來就是將資料寫入文字檔(txt)儲存,以讀寫入模式(W+)開啟一個檔案(library.txt),然後通過write()方法將資料一條一條的寫入檔案。不過,在資訊寫入之前,需要對抓取到的資訊做一些小處理,剛才說過了,findall()方法返回的是一個元組列表,即[[a,b,c],[d,e,f],[g,h,i]]的形式,write()方法是不能對元組進行操作的,所以需要手動將元組翻譯成一條條字串,再儲存到一個列表裡,通過遍曆將每條字串寫入檔案:

 1 def getInformation(self): 2         page = self.getPage() 3         pattern = re.compile('<table.*?id="tb.*?width="50%"><font size=2>(.*?)</font>.*?<tr>.*?<tr>.*?'+ 4                         '<font size=2>(.*?)</font>.*?<font size=2>(.*?)</font>.*?</TABLE>',re.S) 5         items = re.findall(pattern,page) 6  7         contents = [] 8         for item in items: 9             content = item[0]+'    from   '+item[1]+'   to   '+item[2]+'\n'10             contents.append(content)11         self.writeData(contents)12 def writeData(self,contents):13         file = open('libraryBooks.txt','w+')14         for content in contents:15             file.write(content)16         file.close()

  至此,整個爬蟲就算完成了,下面貼上完整代碼:

大功告成:  

 1 __author__='Victor' 2 #_*_ coding:'utf-8' _*_ 3 import urllib 4 import urllib2 5 import cookielib 6 import re 7  8 class library: 9     def __init__(self):10         self.loginURL='http://202.118.250.131/lib/opacAction.do'11         self.queryString = urllib.urlencode({12             'method':'DoAjax',13             'dispatch':'login',14             'registerName':'',15             'rcardNo':'16S137028 0',16             'pwd':'114477yan'17         })18         self.requestURL = self.loginURL + '?' + self.queryString19         self.cookies=cookielib.CookieJar()20         self.handler=urllib2.HTTPCookieProcessor(self.cookies)21         self.opener=urllib2.build_opener(self.handler)22     def getPage(self):23         request1 = urllib2.Request(self.requestURL)24         request2 = urllib2.Request('http://202.118.250.131/lib/opacAction.do?method=init&seq=301')25         result = self.opener.open(request1)26         result = self.opener.open(request2)27         return result.read()28     def getInformation(self):29         page = self.getPage()30         pattern = re.compile('<table.*?id="tb.*?width="50%"><font size=2>(.*?)</font>.*?<tr>.*?<tr>.*?'+31                         '<font size=2>(.*?)</font>.*?<font size=2>(.*?)</font>.*?</TABLE>',re.S)32         items = re.findall(pattern,page)33 34         contents = []35         for item in items:36             content = item[0]+'    from   '+item[1]+'   to   '+item[2]+'\n'37             contents.append(content)38         self.writeData(contents)39     def writeData(self,contents):40         file = open('libraryBooks.txt','w+')41         for content in contents:42             file.write(content)43         file.close()44 45 lib = library()46 lib.getInformation()

  下面就是抓到的借閱資訊,不得不說效果不怎麼樣,不過還是湊合著看把:

                

 

 

原創作品,引用請表明出處:Python爬蟲實戰---抓取圖書館借閱資訊

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.