python爬蟲登入正方教務管理系統獲取成績資料
阿新 • • 發佈:2019-01-21
本程式以四川理工學院教務管理系統為例。。。。
準備工作: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檔案下")