您好,登錄后才能下訂單哦!
這篇文章主要講解了Python3如何實(shí)現(xiàn)模擬登錄和爬取,內(nèi)容清晰明了,對此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會有幫助。
我們先以一個(gè)最簡單的實(shí)例來了解模擬登錄后頁面的抓取過程,其原理在于模擬登錄后 Cookies 的維護(hù)。
1. 本節(jié)目標(biāo)
本節(jié)將講解以 GitHub 為例來實(shí)現(xiàn)模擬登錄的過程,同時(shí)爬取登錄后才可以訪問的頁面信息,如好友動態(tài)、個(gè)人信息等內(nèi)容。
我們應(yīng)該都聽說過 GitHub,如果在我們在 Github 上關(guān)注了某些人,在登錄之后就會看到他們最近的動態(tài)信息,比如他們最近收藏了哪個(gè) Repository,創(chuàng)建了哪個(gè)組織,推送了哪些代碼。但是退出登錄之后,我們就無法再看到這些信息。
如果希望爬取 GitHub 上所關(guān)注人的最近動態(tài),我們就需要模擬登錄 GitHub。
2. 環(huán)境準(zhǔn)備
請確保已經(jīng)安裝好了 requests 和 lxml 庫,如沒有安裝可以參考第 1 章的安裝說明。
3. 分析登錄過程
首先要分析登錄的過程,需要探究后臺的登錄請求是怎樣發(fā)送的,登錄之后又有怎樣的處理過程。
如果已經(jīng)登錄 GitHub,先退出登錄,同時(shí)清除 Cookies。
打開 GitHub 的登錄頁面,鏈接為 https://github.com/login,輸入 GitHub 的用戶名和密碼,打開開發(fā)者工具,將 Preserve Log 選項(xiàng)勾選上,這表示顯示持續(xù)日志,如圖 10-1 所示。
點(diǎn)擊登錄按鈕,這時(shí)便會看到開發(fā)者工具下方顯示了各個(gè)請求過程,如圖 10-2 所示。
點(diǎn)擊第一個(gè)請求,進(jìn)入其詳情頁面,如圖 10-3 所示。
可以看到請求的 URL 為 https://github.com/session,請求方式為 POST。再往下看,我們觀察到它的 Form Data 和 Headers 這兩部分內(nèi)容,如圖 10-4 所示。
Headers 里面包含了 Cookies、Host、Origin、Referer、User-Agent 等信息。Form Data 包含了 5 個(gè)字段,commit 是固定的字符串 Sign in,utf8 是一個(gè)勾選字符,authenticity_token 較長,其初步判斷是一個(gè) Base64 加密的字符串,login 是登錄的用戶名,password 是登錄的密碼。
綜上所述,我們現(xiàn)在無法直接構(gòu)造的內(nèi)容有 Cookies 和 authenticity_token。下面我們再來探尋一下這兩部分內(nèi)容如何獲取。
在登錄之前我們會訪問到一個(gè)登錄頁面,此頁面是通過 GET 形式訪問的。輸入用戶名密碼,點(diǎn)擊登錄按鈕,瀏覽器發(fā)送這兩部分信息,也就是說 Cookies 和 authenticity_token 一定是在訪問登錄頁的時(shí)候設(shè)置的。
這時(shí)再退出登錄,回到登錄頁,同時(shí)清空 Cookies,重新訪問登錄頁,截獲發(fā)生的請求,如圖 10-5 所示。
訪問登錄頁面的請求如圖所示,Response Headers 有一個(gè) Set-Cookie 字段。這就是設(shè)置 Cookies 的過程。
另外,我們發(fā)現(xiàn) Response Headers 沒有和 authenticity_token 相關(guān)的信息,所以可能 authenticity_token 還隱藏在其他的地方或者是計(jì)算出來的。我們再從網(wǎng)頁的源碼探尋,搜索相關(guān)字段,發(fā)現(xiàn)源代碼里面隱藏著此信息,它是一個(gè)隱藏式表單元素,如圖 10-6 所示。
現(xiàn)在我們已經(jīng)獲取到所有信息,接下來實(shí)現(xiàn)模擬登錄。
4. 代碼實(shí)戰(zhàn)
首先我們定義一個(gè) Login 類,初始化一些變量:
class Login(object): def __init__(self): self.headers = { 'Referer': 'https://github.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36', 'Host': 'github.com' } self.login_url = 'https://github.com/login' self.post_url = 'https://github.com/session' self.logined_url = 'https://github.com/settings/profile' self.session = requests.Session()
這里最重要的一個(gè)變量就是 requests 庫的 Session,它可以幫助我們維持一個(gè)會話,而且可以自動處理 Cookies,我們不用再去擔(dān)心 Cookies 的問題。
接下來,訪問登錄頁面要完成兩件事:一是通過此頁面獲取初始的 Cookies,二是提取出 authenticity_token。
在這里我們實(shí)現(xiàn)一個(gè) token() 方法,如下所示:
from lxml import etree def token(self): response = self.session.get(self.login_url, headers=self.headers) selector = etree.HTML(response.text) token = selector.xpath('//div/input[2]/@value')[0] return token
我們用 Session 對象的 get() 方法訪問 GitHub 的登錄頁面,然后用 XPath 解析出登錄所需的 authenticity_token 信息并返回。
現(xiàn)在已經(jīng)獲取初始的 Cookies 和 authenticity_token,開始模擬登錄,實(shí)現(xiàn)一個(gè) login() 方法,如下所示:
def login(self, email, password): post_data = { 'commit': 'Sign in', 'utf8': '✓', 'authenticity_token': self.token(), 'login': email, 'password': password } response = self.session.post(self.post_url, data=post_data, headers=self.headers) if response.status_code == 200: self.dynamics(response.text) response = self.session.get(self.logined_url, headers=self.headers) if response.status_code == 200: self.profile(response.text)
首先構(gòu)造一個(gè)表單,復(fù)制各個(gè)字段,其中 email 和 password 是以變量的形式傳遞。然后再用 Session 對象的 post() 方法模擬登錄即可。由于 requests 自動處理了重定向信息,我們登錄成功后就可以直接跳轉(zhuǎn)到首頁,首頁會顯示所關(guān)注人的動態(tài)信息,得到響應(yīng)之后我們用 dynamics() 方法來對其進(jìn)行處理。接下來再用 Session 對象請求個(gè)人詳情頁,然后用 profile() 方法來處理個(gè)人詳情頁信息。
其中,dynamics() 方法和 profile() 方法的實(shí)現(xiàn)如下所示:
def dynamics(self, html): selector = etree.HTML(html) dynamics = selector.xpath('//div[contains(@class, "news")]//div[contains(@class, "alert")]') for item in dynamics: dynamic = ' '.join(item.xpath('.//div[@class="title"]//text()')).strip() print(dynamic) def profile(self, html): selector = etree.HTML(html) name = selector.xpath('//input[@id="user_profile_name"]/@value')[0] email = selector.xpath('//select[@id="user_profile_email"]/option[@value!=""]/text()') print(name, email)
在這里,我們?nèi)匀皇褂?XPath 對信息進(jìn)行提取。在 dynamics() 方法里,我們提取了所有的動態(tài)信息,然后將其遍歷輸出。在 prifile() 方法里,我們提取了個(gè)人的昵稱和綁定的郵箱,然后將其輸出。
這樣,整個(gè)類的編寫就完成了。
5. 運(yùn)行
我們新建一個(gè) Login 對象,然后運(yùn)行程序,如下所示:
if __name__ == "__main__": login = Login() login.login(email='cqc@cuiqingcai.com', password='password')
在 login() 方法傳入用戶名和密碼,實(shí)現(xiàn)模擬登錄。
可以看到控制臺有類似如下輸出:
GrahamCampbell starred nunomaduro/zero-framework GrahamCampbell starred nunomaduro/laravel-zero happyAnger6 created repository happyAnger6/nodejs_chatroom viosey starred nitely/Spirit lbgws2 starred Germey/TaobaoMM EasyChris starred ageitgey/face_recognition callmewhy starred macmade/GitHubUpdates sindresorhus starred sholladay/squatter SamyPesse starred graphcool/chromeless wbotelhos starred tkadlec/grunt-perfbudget wbotelhos created repository wbotelhos/eggy leohxj starred MacGesture/MacGesture GrahamCampbell starred GrahamCampbell/Analyzer EasyChris starred golang/go mitulgolakiya starred veltman/flubber liaoyuming pushed to student at Germey/SecurityCourse leohxj starred jasonslyvia/a-cartoon-intro-to-redux-cn ruanyf starred ericchiang/pup ruanyf starred bpesquet/thejsway louwailou forked Germey/ScrapyTutorial to louwailou/ScrapyTutorial Lving forked shadowsocksr-backup/shadowsocksr to Lving/shadowsocksr qifuren1985 starred Germey/ADSLProxyPool QWp6t starred laravel/framework Germey ['1016903103@qq.com', 'cqc@cuiqingcai.com']
可以發(fā)現(xiàn),我們成功獲取到關(guān)注的人的動態(tài)信息和個(gè)人的昵稱及綁定郵箱。模擬登錄成功!
看完上述內(nèi)容,是不是對Python3如何實(shí)現(xiàn)模擬登錄和爬取有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。