用Python爬蟲爬取廣州大學教務系統的成績(內網訪問)


用Python爬蟲爬取廣州大學教務系統的成績(內網訪問)

在進行爬取前,首先要了解:

1、什么是CSS選擇器?

每一條css樣式定義由兩部分組成,形式如下: [code] 選擇器{樣式} [/code] 在{}之前的部分就是“選擇器”。
“選擇器”指明了{}中的“樣式”的作用對象,也就是“樣式”作用於網頁中的哪些元素。
可參考:
http://www.w3school.com.cn/cssref/css_selectors.asp
http://www.ruanyifeng.com/blog/2009/03/css_selectors.html

2、常用的三種網頁抓取方法(例子可能不可用,只要看方法就可以了)

正則表達式:

 1 # -*- coding: utf-8 -*-
 2 
 3 import urllib2
 4 import re
 5 
 6 
 7 def scrape(html):
 8     area = re.findall('<tr id="places_area__row">.*?<td\s*class=["\']w2p_fw["\']>(.*?)</td>', html)[0]
 9     return area
10 
11 
12 if __name__ == '__main__':
13     html = urllib2.urlopen('http://example.webscraping.com/view/United-Kingdom-239').read()
14     print scrape(html)

流行的BeautifulSoup模塊:

 1 # -*- coding: utf-8 -*-
 2 
 3 import urllib2
 4 from bs4 import BeautifulSoup
 5 
 6 def scrape(html):
 7     soup = BeautifulSoup(html) 
 8     tr = soup.find(attrs={'id':'places_area__row'}) # locate the area row
 9     # 'class' is a special python attribute so instead 'class_' is used
10     td = tr.find(attrs={'class':'w2p_fw'})  # locate the area tag
11     area = td.text  # extract the area contents from this tag
12     return area
13 
14 if __name__ == '__main__':
15     html = urllib2.urlopen('http://example.webscraping.com/view/United-Kingdom-239').read()
16     print scrape(html)

強大的lxml模塊:

 1 # -*- coding: utf-8 -*-
 2 
 3 import urllib2
 4 import lxml.html
 5 
 6 
 7 def scrape(html):
 8     tree = lxml.html.fromstring(html)
 9     td = tree.cssselect('tr#places_neighbours__row > td.w2p_fw')[0]
10     area = td.text_content()
11     return area
12 
13 if __name__ == '__main__':
14     html = urllib2.urlopen('http://example.webscraping.com/view/United-Kingdom-239').read()
15     print scrape(html)

本文選用第三種網頁抓取的方法:lxml(性能快,使用難度簡單,只是安裝難度相對困難而已,建議直接安裝anaconda)

3、什么是cookie?

在 Internet 中,Cookie 實際上是指小量信息,是由 Web 服務器創建的,將信息存儲在用戶計算機上的文件。一般網絡用戶習慣用其復數形式 Cookies,指某些網站為了辨別用戶身份、進行 Session 跟蹤而存儲在用戶本地終端上的數據,而這些數據通常會經過加密處理。
通常情況下,當用戶結束瀏覽器會話時,系統將終止所有的 Cookie。當 Web 服務器創建了Cookies 后,只要在其有效期內,當用戶訪問同一個 Web 服務器時,瀏覽器首先要檢查本地的Cookies,並將其原樣發送給 Web 服務器。這種狀態信息稱作“Persistent Client State HTTP Cookie” ,簡稱為 Cookies。
具體含義
“Cookie”是小量信息,由網絡服務器發送出來以存儲在網絡瀏覽器上,從而下次這位獨一無二的訪客又回到該網絡服務器時,可從該瀏覽器讀回此信息。這是很有用的,讓瀏覽器記住這位訪客的特定信息,如上次訪問的位置、花費的時間或用戶首選項(如樣式表)。Cookie 是個存儲在瀏覽器目錄的文本文件,當瀏覽器運行時,存儲在 RAM 中。一旦你從該網站或網絡服務器退出,Cookie 也可存儲在計算機的硬驅上。當訪客結束其瀏覽器對話時,即終止的所有 Cookie。
主要用途
服務器可以利用Cookies包含信息的任意性來篩選並經常性維護這些信息,以判斷在HTTP傳輸中的狀態。Cookies最典型的應用是判定注冊用戶是否已經登錄網站,用戶可能會得到提示,是否在下一次進入此網站時保留用戶信息以便簡化登錄手續,這些都是Cookies的功用。另一個重要應用場合是“購物車”之類處理。用戶可能會在一段時間內在同一家網站的不同頁面中選擇不同的商品,這些信息都會寫入Cookies,以便在最后付款時提取信息。

4、csv文件

逗號分隔值(Comma-Separated Values,CSV,有時也稱為字符分隔值,因為分隔字符也可以不是逗號),其文件以純文本形式存儲表格數據(數字和文本)。
可以看成是我們常見的excel文件,只不過是用逗號分隔每一個單元格而已。

 

完整代碼如下:

 1 # -*- coding: utf-8 -*-
 2 
 3 import urllib
 4 import urllib2
 5 import cookielib
 6 import lxml.html
 7 import csv
 8 
 9 # 用戶名、密碼
10 LOGIN_USERNAME = '1406100037'
11 LOGIN_PASSWORD = '******'
12 
13 LOGIN_URL1 = 'https://cas.gzhu.edu.cn/cas_server/login'
14 LOGIN_URL2 = 'http://202.192.18.189/login_gzdx.aspx'
15 
16 
17 def parse_form(html):
18     '''
19     獲取表單提交所需的所有隱藏域
20     :param html: html代碼
21     :return: 該頁面的表單提交所需的所有隱藏域
22     '''
23     tree = lxml.html.fromstring(html)
24     data = {}
25     for e in tree.cssselect('form input'):
26         if e.get('name'):
27             data[e.get('name')] = e.get('value').encode('utf-8')
28     return data
29 
30 
31 def getRecordsHTML():
32     '''
33     發送POST請求提交表單
34     使用cookie登錄數字廣大
35     再次使用cookie登錄"http://202.192.18.189/login_gzdx.aspx"
36     然后再次發送POST請求提交表單查詢成績
37     :return:查詢成績的html
38     '''
39     mcj = cookielib.MozillaCookieJar('mcj.txt')
40     opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(mcj))
41     html = opener.open(LOGIN_URL1).read()
42     data = parse_form(html)
43     data['username'] = LOGIN_USERNAME
44     data['password'] = LOGIN_PASSWORD
45     encoded_data = urllib.urlencode(data)
46     request = urllib2.Request(LOGIN_URL1, encoded_data)
47     response = opener.open(request)
48     print(response.geturl())
49 
50     request = urllib2.Request(LOGIN_URL2, encoded_data)
51     response = opener.open(request)
52     print(response.geturl())
53 
54     html = opener.open(response.geturl()).read()
55     tree = lxml.html.fromstring(html)
56     path = tree.cssselect('#headDiv > ul > li:nth-child(6) > ul > li:nth-child(1) > a')[0].get('href')
57     URL3 = 'http://202.192.18.185/' + \
58         urllib.quote(path.encode('gbk'), safe='?=&')
59     print(URL3)
60 
61     html = opener.open(URL3).read()
62     data = parse_form(html)
63     newData = {
64         '__VIEWSTATE': data['__VIEWSTATE'],
65         '__VIEWSTATEGENERATOR': data['__VIEWSTATEGENERATOR'],
66         'Button2': data['Button2']
67     }
68     # print('data=', newData)
69 
70     encoded_data = urllib.urlencode(newData)
71     request = urllib2.Request(URL3, encoded_data)
72     response = opener.open(request)
73     mcj.save(ignore_discard=True, ignore_expires=True)
74     html = response.read()
75     return html
76 
77 
78 def main():
79     '''
80     提取並保存成績到“在校學習成績.csv”文件中
81     '''
82     writer = csv.writer(open('在校學習成績.csv', 'w'))
83     tree = lxml.html.fromstring(getRecordsHTML())
84     row = []
85 
86     for i in xrange(1, 100):
87         for j in xrange(15):
88             try:
89                 row.append(tree.cssselect('#Datagrid1 > tr:nth-child(%s) > td' % i)[j].text_content().encode('utf-8'))
90             except Exception as e:
91                 break
92         writer.writerow(row)
93         row = []
94 
95 if __name__ == '__main__':
96     main()

運行結果:

生成的csv文件如下:

 

因為上面的代碼已經將cookie信息保存下來了,下次訪問我們就可以用下面的代碼:

 1 # -*- coding: utf-8 -*-
 2 
 3 import urllib
 4 import urllib2
 5 import cookielib
 6 import lxml.html
 7 import csv
 8 
 9 def parse_form(html):
10     '''
11     獲取表單提交所需的所有隱藏域
12     :param html: html代碼
13     :return: 該頁面的表單提交所需的所有隱藏域
14     '''
15     tree = lxml.html.fromstring(html)
16     data = {}
17     for e in tree.cssselect('form input'):
18         if e.get('name'):
19             data[e.get('name')] = e.get('value').encode('utf-8')
20     return data
21 
22 def getRecordsHTML():
23     mcj = cookielib.MozillaCookieJar()
24     mcj.load('mcj.txt', ignore_discard=True, ignore_expires=True)
25     opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(mcj))
26     URL3 = 'http://202.192.18.185/xscj_gc.aspx?xh=1406100037'
27     html = opener.open(URL3).read()
28     data = parse_form(html)
29     newData = {
30         '__VIEWSTATE': data['__VIEWSTATE'],
31         '__VIEWSTATEGENERATOR': data['__VIEWSTATEGENERATOR'],
32         'Button2': data['Button2']
33     }
34 
35     encoded_data = urllib.urlencode(newData)
36     request = urllib2.Request(URL3, encoded_data)
37     response = opener.open(request)
38     html = response.read()
39     return html
40 
41 
42 def main():
43     writer = csv.writer(open('在校學習成績2.csv', 'w'))
44     tree = lxml.html.fromstring(getRecordsHTML())
45     row = []
46 
47     for i in xrange(1, 100):
48         for j in xrange(15):
49             try:
50                 row.append(tree.cssselect('#Datagrid1 > tr:nth-child(%s) > td' % i)[j].text_content().encode('utf-8'))
51             except Exception as e:
52                 break
53         writer.writerow(row)
54         row = []
55 
56 if __name__ == '__main__':
57     main()

 

本文地址:http://www.cnblogs.com/jacen789/p/8058897.html

更新版本的爬蟲:https://github.com/Jacen789/GzhuGradesCrawler

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM