爬取需要登錄的頁面


對於一些公共的站點,比如糗事百科 、新聞站點等,不需要登錄就能通過 urllib2.urlopen() 打開並爬取我們想要的資源
但像一些私密的站點,比如管理后台,數據中心等,需要登錄后才能使用 urllib2.urlopen() 打開並爬取我們想要的資源
需要登錄的站點,我們在使用 urllib2.urlopen() 時需要向服務器傳遞一些數據,比如用戶名 、密碼等,傳遞數據通常有 GET 和 POST 兩種方法

GET 是直接以網址形式打開,網址中包含了所有的參數,瀏覽器會把 http header 和 data 一並發送出去,服務器響應200(返回數據)
POST 是瀏覽器先發送 http header,服務器響應100 continue,瀏覽器再發送 data,服務器響應200 ok(返回數據),具體用什么方法是由服務器來決定的

可以參考 Django 是如何進行數據傳遞的:https://www.cnblogs.com/pzk7788/p/10340215.html


使用 POST 方式登錄並爬取資源的流程:

第一步,先打開登錄頁面,然后按 F12 打開開發者工具


第二步,登錄進去,然后找到 POST 請求,記得要勾選如下的 "Preserve log"


第三步,查看 POST 請求,找到表單數據


有些網站的表單數據包含了 Token 信息,如果要獲取 Token 信息需要退出登錄,然后在登錄框右鍵點擊檢查:


最后,根據表單數據使用 POST 方式模擬登錄

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import re
import sys
import urllib
import urllib2
import cookielib

class AdminSite(object):

    def __init__(self):
        self.login_url = 'http://www.xxxx.com:8899/accounts/login/'    # 登錄頁面的URL
        self.request_url = 'http://www.xxxx.com:8899/yunwei/index/'    # 要爬取的頁面的URL
        self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36'}
        
    def getPage(self):
        cookie = cookielib.CookieJar()
        handler = urllib2.HTTPCookieProcessor(cookie)
        self.opener = urllib2.build_opener(handler)

        try:
            request = urllib2.Request(url=self.request_url, headers=self.headers)
            response = self.opener.open(request)
            return response.read()
        except urllib2.URLError, e:
            if hasattr(e, 'code'):
                print '連接服務器失敗,錯誤代碼:%s' % e.code
            if hasattr(e, 'reason'):
                print '連接服務器失敗,失敗原因:%s' % e.reason
            else:
                print '連接服務器失敗,失敗原因:%s' % e
            sys.exit(1)
          
    def getToken(self):
        page = self.getPage()
        regular = re.compile(r"<form.*?<input.*?value='(.*?)'.*?>", re.S)
        token = regular.search(page)
        if token:
            return token.group(1)
        else:
            return None

    def login(self):
        form_data = {'csrfmiddlewaretoken': self.getToken(),
                     'username': 'xxxxxx',
                     'password': 'xxxxxx',
                     'next': '/yunwei/index/'}
        self.post_data = urllib.urlencode(form_data) 
        try:
            request = urllib2.Request(url=self.login_url, data=self.post_data, headers=self.headers)
            response = self.opener.open(request)
            print response.read()
            return response.read()
        except urllib2.URLError, e:
            if hasattr(e, 'code'):
                print '連接服務器失敗,錯誤代碼:%s' % e.code
            if hasattr(e, 'reason'):
                print '連接服務器失敗,失敗原因:%s' % e.reason
            else:
                print '連接服務器失敗,失敗原因:%s' % e
            sys.exit(1)

if __name__ == '__main__':
    obj = AdminSite()
    obj.login()


使用 urllib2 編寫很復雜,我們可以使用 requests 來模擬登陸:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import re
import sys
import urllib2
import requests

class AdminSite(object):

    def __init__(self):
        self.login_url = 'http://www.xxxx.com:8899/accounts/login/'    # 登錄頁面的URL
        self.request_url = 'http://www.xxxx.com:8899/yunwei/index/'    # 要爬取的頁面的URL
        self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36'}
        
    def getPage(self):
        self.session = requests.session()
        try:
            response = self.session.get(url=self.request_url, headers=self.headers, verify=False)
            return response.text
        except urllib2.URLError, e:
            if hasattr(e, 'code'):
                print '連接服務器失敗,錯誤代碼:%s' % e.code
            if hasattr(e, 'reason'):
                print '連接服務器失敗,失敗原因:%s' % e.reason
            else:
                print '連接服務器失敗,失敗原因:%s' % e
            sys.exit(1)
          
    def getToken(self):
        page = self.getPage()
        regular = re.compile(r"<form.*?<input.*?value='(.*?)'.*?>", re.S)
        token = regular.search(page)
        if token:
            return token.group(1)
        else:
            return None

    def login(self):
        form_data = {'csrfmiddlewaretoken': self.getToken(),
                     'username': 'xxxxxx',
                     'password': 'xxxxxx',
                     'next': '/yunwei/index/'}
        try:
            response = self.session.post(url=self.login_url, data=self.post_data, headers=self.headers)
            return response.text
        except urllib2.URLError, e:
            if hasattr(e, 'code'):
                print '連接服務器失敗,錯誤代碼:%s' % e.code
            if hasattr(e, 'reason'):
                print '連接服務器失敗,失敗原因:%s' % e.reason
            else:
                print '連接服務器失敗,失敗原因:%s' % e
            sys.exit(1)

if __name__ == '__main__':
    obj = AdminSite()
    obj.login()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

      


免責聲明!

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



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