1. 程式人生 > >python爬蟲登入正方教務管理系統獲取成績資料

python爬蟲登入正方教務管理系統獲取成績資料

本程式以四川理工學院教務管理系統為例。。。。

準備工作:1.ruquests庫的使用(或者urllib也可行)

    2.正則表示式的書寫

                    3.HTTP通訊基礎

                    4.一些解析庫的使用

準備一個瀏覽器監視工具,這裡我是用的是fiddler下載地址點選開啟連結

登入官網獲取到登入系統url:http://61.139.105.138/default2.aspx


這裡可以知道瀏覽器是先請求登入頁面,讓後轉到去獲取驗證碼圖片。

仔細分析驗證碼連線發現:


這個請求方式是get但包含有cookies

所以模擬登入前獲取驗證碼時需要帶上cookies否則登入會一直提示驗證碼錯誤


檢視傳送的請求

__VIEWSTATE可以在登入頁面的指令碼中捕捉到 後面的資料便是post請求需要帶上的資料

最後對於網頁上的驗證碼問題,這裡選擇下載驗證碼圖片並自動開啟。

下面貼上模擬登入的程式碼

import requests
import re
from html.parser import *
import urllib.request
import os
x=[]
state=[]
class Scraper(HTMLParser):
    def handle_starttag(self,tag,attrs):
        if tag=='img':#驗證碼
            attrs=dict(attrs)
            if(attrs.__contains__('id')):
                x.append(attrs["src"])
        if tag=='input':#viewstate
            attrs=dict(attrs)
            if attrs.__contains__('name'):
                if attrs['name']=='__VIEWSTATE':
                    state.append(attrs['value'])

webpage=requests.get(url="http://61.139.105.138/default2.aspx")
Cookie=webpage.cookies#獲取網頁cookies
date=webpage.text
parser=Scraper()
parser.feed(date)
headers={
    'User-Agent':r'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0;  TheWorld 7)',
    }
while True:
    url="http://61.139.105.138/CheckCode.aspx"#驗證碼所在連線
    pic=requests.get(url,cookies=Cookie,headers=headers)
    if os.path.exists(r'f://yanzheng.jpg'):
        os.remove(r'f://yanzheng.jpg')
    with open(r'f://yanzheng.jpg','wb')as f:
        f.write(pic.content)
        f.close()
    username=input("輸入使用者名稱: ")
    password=input("輸入密碼 ")

    os.startfile(r'f:yanzheng.jpg')
    ycode=input("輸入彈出的驗證碼: ")

    payload={
             '__VIEWSTATE':state[0],
             'txtUserName':username,
             'TextBox2':password,
             'txtSecretCode':ycode,
             'RadioButtonList1':'%D1%A7%C9%FA',
             'Button1':"",
             'lbLanguage':'',
             'hidPdrs':'',
             'hidsc':'',
            }
    Log_in=r"http://61.139.105.138/default2.aspx"

    r=requests.post(url=Log_in,data=payload,headers=headers,cookies=Cookie)
    #用正則算了
    pat=r'<title>(.*?)</title>'#獲取標題的正則表示式
    x=re.findall(pat,r.text)
    if(x[0]=="歡迎使用正方教務管理系統!請登入"):
        print("登陸失敗")
        albert="defer>alert\('(.*?)'\)"
        err=re.findall(albert,r.text)
        print(err[0])
    else:
        print("登陸成功")


過程中遇到需要判斷登入是否成功,這裡選擇識別標記字元,我這邊抓取了網頁的標題,如果不成功標題就會是"歡迎使用正方教務管理系統!請登入"

在登入失敗的情況下依然可以通過正則表示式獲取登入失敗資訊

最後便是進入成績查詢介面,依舊先通過fiddler觀察瀏覽器的行為:


    可以看出get請求相關資訊是學號,姓名,專案程式碼(姓名可以在登入頁面抓取)

    值得注意的是headers中必須含有referer否則會被彈出

    下面貼出相關程式碼:

 #抓一下名字
        catch='<span id="xhxm">(.*?)</span></em>'
        name=re.findall(catch,r.text)
        name=name[0]
        name=name[:-2]
        print(name)
        break
name=str(name).replace(r'\x','%')#擴大適用性
name=name.upper()
name=name[2:]

lheaders={
    'User-Agent':r'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0;  TheWorld 7)',
     'Referer':'http://61.139.105.138/xs_main.aspx?xh='+username#擴大適用性
    }
html=requests.get("http://61.139.105.138/xscjcx_dq.aspx?xh="+username+"&xm="+name+"&gnmkdm=N121605",cookies=Cookie,headers=lheaders)
#最後處理成績資訊
selectall=r'<td>(.*?)</td>'*17
result=re.findall(selectall,html.text)
xm=result[0]#專案分離
forma=[]
temp=''
for i in range(17):forma.append('')#17位的資料存放處理好的資料
for index in range(17):
    for item in result:
        temp=format("% -15s"%str(item[index]).strip())
        forma[index]+=temp


for each in forma:
    print(each)
input("查詢結束按下任意鍵退出")   


這就是整個爬蟲實現的過程,允許相關輸入錯誤後再次輸入

最後貼上整個專案程式碼:

import requests
import re
from html.parser import *
import urllib.request
import os
import csv
x=[]
state=[]
class Scraper(HTMLParser):
    def handle_starttag(self,tag,attrs):
        if tag=='img':#驗證碼
            attrs=dict(attrs)
            if(attrs.__contains__('id')):
                x.append(attrs["src"])
        if tag=='input':#viewstate
            attrs=dict(attrs)
            if attrs.__contains__('name'):
                if attrs['name']=='__VIEWSTATE':
                    state.append(attrs['value'])

webpage=requests.get(url="http://61.139.105.138/default2.aspx")
Cookie=webpage.cookies#獲取網頁cookies
date=webpage.text
parser=Scraper()
parser.feed(date)
headers={
    'User-Agent':r'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0;  TheWorld 7)',
    }
while True:
    url="http://61.139.105.138/CheckCode.aspx"#驗證碼所在連線
    pic=requests.get(url,cookies=Cookie,headers=headers)
    if os.path.exists(r'f://yanzheng.jpg'):
        os.remove(r'f://yanzheng.jpg')
    with open(r'f://yanzheng.jpg','wb')as f:
        f.write(pic.content)
        f.close()
    username=input("輸入使用者名稱: ")
    password=input("輸入密碼 ")

    os.startfile(r'f:yanzheng.jpg')
    ycode=input("輸入彈出的驗證碼: ")

    payload={
             '__VIEWSTATE':state[0],
             'txtUserName':username,
             'TextBox2':password,
             'txtSecretCode':ycode,
             'RadioButtonList1':'%D1%A7%C9%FA',
             'Button1':"",
             'lbLanguage':'',
             'hidPdrs':'',
             'hidsc':'',
            }
    Log_in=r"http://61.139.105.138/default2.aspx"

    r=requests.post(url=Log_in,data=payload,headers=headers,cookies=Cookie)
    #用正則算了
    pat=r'<title>(.*?)</title>'#獲取標題的正則表示式
    x=re.findall(pat,r.text)
    if(x[0]=="歡迎使用正方教務管理系統!請登入"):print("登陸失敗")
    else:
        print("登陸成功")
        #抓一下名字
        catch='<span id="xhxm">(.*?)</span></em>'
        name=re.findall(catch,r.text)
        name=name[0]
        name=name[:-2]
        print(name)
        break
name=str(name).replace(r'\x','%')#擴大適用性
name=name.upper()
name=name[2:]

lheaders={
    'User-Agent':r'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0;  TheWorld 7)',
     'Referer':'http://61.139.105.138/xs_main.aspx?xh='+username#擴大適用性
    }
html=requests.get("http://61.139.105.138/xscjcx_dq.aspx?xh="+username+"&xm="+name+"&gnmkdm=N121605",cookies=Cookie,headers=lheaders)
#最後處理成績資訊
selectall=r'<td>(.*?)</td>'*17
result=re.findall(selectall,html.text)
xm=result[0]#專案分離
forma=[]
csvfile=open('f://result.csv','w',newline='')
writer=csv.writer(csvfile)
temp=''
for i in range(17):forma.append('')#17位的資料存放處理好的資料
for index in range(17):
    for item in result:
        temp=format("% -15s"%str(item[index]).strip())
        forma[index]+=temp

for each in forma:
    print(each)

for num,item in enumerate(result):
    for index,value in enumerate(item):#處理下result裡面的無規則資料
        if value==" ":
            result[num][index]=''

for item in result:
    writer.writerow(item)
csvfile.close()
input("爬蟲完成,結果存在F盤result.csv檔案下")