最近需要實現獲取個人京東訂單信息的功能,利用了requests+beautifulsoup來實現。
requests是python的第三方庫,相比之前常用的python標準庫中的urllib2,requests簡直不要好用太多,具體實現思路是,首先使用firefox+firebug找到京東登陸所需要的信息,利用requests的get獲取需要模擬登陸的信息,post之后獲取cookie,然后帶著cookie訪問相應訂單的網頁就可以得到訂單信息了。
打開京東登陸的網頁,使用賬戶登陸京東,在firebug上查看傳遞的參數
loginname是登陸的用戶名,loginpwd和nloginpwd都是登陸的密碼。以machine開頭的三個參數傳遞參數為空,authcode是驗證碼,如果京東檢測到你登陸狀態有異常就會提示輸入驗證碼。
經過測試,我們需要獲取的參數有uuid、-t、和eAHDKkiNwP三個參數
回到京東登陸界面尋找這三個參數,在登陸界面的源代碼中可以看到有個id名稱為formlogin的form標簽
正好全部包含了登陸需要傳遞的參數,利用Beautifulsoup將對于name的value提取出來,放在構造post信息的字典中,將構造好的字典通過requests的post方法獲取到登陸的cookie。這樣,得到訂單信息我們已經完成了一大半了。
下面是具體實現的部分源碼
import requests
from bs4 import BeautifulSoup
header= {
'Host':'order.jd.com',
'Upgrade-Insecure-Requests':'1',
'Connection':'keep-alive',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2700.0 Safari/537.36',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate, sdch',
'Accept-Language':'zh-CN,zh;q=0.8',
'Cache-Control':'max-age=0'
}
導入相應的包之后,需要構造header,網站服務器通過host來確定訪問的網頁,User-Agent是用戶使用瀏覽器版本,系統的標簽。許多網站會檢查header中的host和User-Agent信息是否正確合理,不會處理未帶正確header的請求,header可以在firebug上查看,這里我直接粘貼firebug上的,如果是大型的爬蟲可以構造一個header池,每隔一段時間變更header中的User-Agent,簡單的爬蟲就不需要做的這么麻煩啦。
sessions = requests.session()
login_page=sessions.get('https://passport.jd.com/new/login.aspx',headers = header)
login_soup = BeautifulSoup(login_page.text,'lxml')
login_postinfo = login_soup.find_all('form',attrs = {'id' : 'formlogin'})[0].find_all('input')
先構造一個sessions來幫助我們處理獲取到的cookie,session可以自動處理cookie字符。
獲取到登陸界面的text之后,先轉換為beautiful可以處理的格式,login_postinfo為上文提到的formlogin下的所有input標簽信息
uuid = login_soup.find_all('input',attrs = {'id' : 'uuid'})[0]['value']
_t = login_soup.find_all('input',attrs = {'name' : '_t'})[0]['value']
利用beautifulsoup獲取到uuid和_t
for input_info in login_postinfo:
if len(input_info['value']) == 5:
str1 = input_info['name']
str2 = input_info['value']
在提取最后一個關鍵key時和之前的不一樣,它的key名是input標簽中的name,value是標簽中的value,所以我們無法按照name或id來提取,它們是一直在變化的,但是可以觀察到一個規律,value值都是5個英文字母組成的,而input標簽其他的value要不為空,要不有下劃線或是一串很長的字符串,所以可以根據value的字符長度來定位到我們所需要的input
post_info = {
'uuid':uuid,
'loginname':'XXXXX',
'loginpwd':'XXXX',
'machineCpu':'',
'machineDisk':'',
'machineNet':'',
'nloginpwd':'XXXX',
str1:str2,
'_t':_t,
'authcode':''}
content = sessions.post('http://passport.jd.com/uc/loginService',data=post_info,headers = header)
構造post信息的字典,通過sessions發送帶著post字典的請求,可以得到success的信息
然后我們就可以訪問相應的界面獲取想要的信息了