1. 程式人生 > >利用python爬取yapi後臺介面

利用python爬取yapi後臺介面

解決的問題:檢測公司釋出系統之中,遺漏的介面路徑地址。

採取的方法:爬取yapi管理後臺,爬取所有的介面路徑,同時檢測這個path路徑是否在釋出系統之中(如果不在釋出系統之後,通過域名訪問,會提示沒有許可權)

好了瞭解了背景之後 我就開始開工了。

一、瞭解yapi 

在這裡小編看到了 左邊是產品  右邊是產品對應的模組名稱  點選模組名稱 我們可以看到很多個介面地址。

二、分析問題

瞭解到yapi的大致情況之後,我們知道點選產品,之後點選產品所屬的模組,每個模組下面有對應模組的介面地址,相比就知道了,就二個迴圈解決的問題

1.根據產品id(這裡我叫做group_id ) 找尋所有的模組id ,分析如下

2.根據模組id,找尋所有的介面路徑。

3.找到一個介面路徑  就通過requests請求對應地址訪問一下,如果許可權不足的就儲存下來。

初略的瞭解了一下之後,我們發現獲取模組id,和獲取介面路徑哪裡,可能會分頁,為了避免進行翻頁爬蟲,簡化指令碼 小編這裡先將分頁條數(limit)擴大了,另外還有一個地方,就是檢查許可權不足的時候,返回的格式是byte的我們需要decode轉成str字串的格式,但是呢,有些介面返回的又不是byte,所以當你把所有的介面都強制decode的時候,可能會報異常,這裡我通過使用"pass"得到了解決。

當然這裡換種策略 不選擇爬yapi後臺的話,也可以連線資料庫進行查詢在校驗的(mongodb)

三、程式碼部分

# author: xiejiangpeng
# time:2018/11/7/20:35
# python:python3.6
# message: 連線api.host.com獲取介面 校驗許可權
import requests
import json
import time


class CheckUrlJurisdiction(object):
    """
    例項初始化欄位說明
    userapi: api後臺登入賬號
    useradmin: base後臺登入賬號
    passwdapi: api後臺登入密碼
    passwdadmin: base後臺登入密碼
    group_id: api後臺需要檢測產品id(base:35    團購:176)
    self.countTotal: path總數
    self.countnum: path許可權不足數量
    self.pathmodle: path所屬模組名稱
    self.pathname: path詳細名稱
    self.time: 執行花費時間
    """

    def __init__(self, userapi, useradmin, passwdapi, passwdadmin, group_id):
        self.userapi = userapi
        self.useradmin = useradmin
        self.passwdapi = passwdapi
        self.passwdadmin = passwdadmin
        self.group_id = group_id
        self.countTotal = 0
        self.countnum = 0
        self.pathmodle = ""
        self.pathname = ""
        self.time = float()
        self.apiurl = "http://api.host.com"
        self.adminurl = "http://base.host.com"
        self.api = requests.session()
        self.admin = requests.session()
        """api_login"""
        loginjson = {'email': self.userapi,
                     'password': self.passwdapi}
        loginheader = {'Content-Type': 'application/json;charset=UTF-8'}
        print("api後臺登入狀態:", self.api.post(url=self.apiurl + "/api/user/login", data=json.dumps(loginjson), verify=False,
                                          headers=loginheader).json().get("errmsg"))
        """admin_login"""
        loginbody = {'name': useradmin, 'password': passwdadmin, 'verify_code': ''}
        print("base後臺登入狀態: %s" % self.admin.post(url=self.adminurl + "/superAdmin/loginSuper/login", data=loginbody,
                                                 verify=False).json().get("status"))

    def geturlpath(self):
        """根據group_id獲取對應模組id limit為每頁模組條數"""
        print("正在檢測釋出系統遺漏的介面地址(本次程式檢測所花費時間可能較長,請耐心等待)")
        starttime = time.clock()
        getid = {'group_id': self.group_id, 'page': '1', 'limit': '50'}
        ids = self.api.get(url=self.apiurl + "/api/project/list", verify=False, params=getid).json().get("data").get(
            "list")
        for i in range(0, len(ids)):
            self.pathmodle = ids[i].get("name")
            self.get_path_by_id(ids[i].get("_id"))
        timeend = time.clock()
        self.time = str("%.2f" % (timeend - starttime))

    """通過模組id找尋path"""

    def get_path_by_id(self, _id):
        """避免翻頁,條數設定為999"""
        details = self.api.get(self.apiurl + "/api/interface/list?page=1&limit=999&project_id=%s" % _id,
                               verify=False).json()
        for j in range(0, len(details.get("data").get("list"))):
            self.countTotal += 1
            path = details.get("data").get("list")[j].get("path")
            self.pathname = details.get("data").get("list")[j].get("title")
            self.check_path(path)

    """根據path提取出沒有許可權的資訊"""

    def check_path(self, path):

        """檢查是否有許可權"""
        result = self.admin.get(url=self.adminurl + path, verify=False)
        if result.status_code == 200:
            try:
                if result.content.decode("utf-8").find("許可權") != -1:
                    print("%s  url資訊:%s/%s" %
                          (path, self.pathmodle, self.pathname))
                    self.countnum += 1
            except UnicodeDecodeError:
                pass


if __name__ == "__main__":
    xiejiangpeng = CheckUrlJurisdiction("apiuser", "baseuser", "apipasswd", "basepasswd", "group_id")
    xiejiangpeng.geturlpath()
    print("總共檢測path數 %s" % xiejiangpeng.countTotal)
    print("許可權不足path數 %s" % xiejiangpeng.countnum)
    print("本次檢測所需時間為 %s秒" % xiejiangpeng.time)

四、執行效果

八百五十七個介面檢測完畢  總共花費時間三分鐘不到 找出許可權不足的數量為15個

 

 

好了分享到此結束,指令碼需要優化的地方還有很多,比如:執行完畢之後通過郵件的形式傳送給對應的人員,並且還可以優化一下產品id,以及模組下面對應的url採取分頁爬蟲的形式等等等。以後給大家分享其他的有關資訊