百度AI人臉注冊源碼詳解

Summer

1先舷、起點AppConfig.client.addUser(image, imageType, groupId, userId, options)調用人臉注冊api,從addUser進入

def addUser(self, image, image_type, group_id, user_id, options=None):
    """
        人臉注冊
    """
    options = options or {}

    data = {}
    data['image'] = image
    data['image_type'] = image_type
    data['group_id'] = group_id
    data['user_id'] = user_id

    data.update(options)
    return self._request(self.__userAddUrl, json.dumps(data, ensure_ascii=False), {
        'Content-Type': 'application/json',
    })

詳解:由此可見我們需要傳四個必要參數(shù)image, image_type, group_id, user_id险掀,一個可選參數(shù)options魁索;
     接下來是 return self._request(self.__userAddUrl, json.dumps(data, ensure_ascii=False)履植,根據(jù)__userAddUrl和序列化字段以及Content-Type來發(fā)送請求烫堤,看一下__userAddUrl是__userAddUrl = 'https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add',也就是說是向這個路由發(fā)送請求昧谊;

2刽虹、那就要看一下_request請求是怎么發(fā)送的,點進去看

def _request(self, url, data, headers=None):
    """
       self._request('', {})
    """
    try:
        result = self._validate(url, data)  # 判斷路由和數(shù)據(jù)是否有效
        if result != True:
            return result

        authObj = self._auth()  # 實例化認證對象
        params = self._getParams(authObj)  # 實例化參數(shù)對象呢诬,傳入的是認證對象涌哲,這里的參數(shù)就是access token

        data = self._proccessRequest(url, params, data, headers)  # 對請求進行處理,傳入路由尚镰,參數(shù)阀圾,數(shù)據(jù)和報頭
        headers = self._getAuthHeaders('POST', url, params, headers)  # 對報頭進行認證,我猜測這里面有反爬措施
         # 通過實例化的對象發(fā)送請求狗唉,攜帶的參數(shù)為路由初烘,數(shù)據(jù),access token參數(shù)分俯,報頭肾筐,認證,超時時間缸剪;
         # 這里的__connectTimeout是自定義的連接超時時間吗铐,__socketTimeout是通過打開的連接傳輸數(shù)據(jù)的超時時間,單位都為ms
        response = self.__client.post(url, data=data, params=params,
                        headers=headers, verify=False, timeout=(
                            self.__connectTimeout,
                            self.__socketTimeout,
                        ), proxies=self._proxies
                    ) 
        obj = self._proccessResult(response.content)  # 最后返回的結果對象
        # 如果云端未注冊并且調用接口的返回錯誤碼是110,表示Access Token失效杏节,這時就要再次進行認證
        if not self._isCloudUser and obj.get('error_code', '') == 110:  
            authObj = self._auth(True)
            params = self._getParams(authObj)
            response = self.__client.post(url, data=data, params=params,
                            headers=headers, verify=False, timeout=(
                                self.__connectTimeout,
                                self.__socketTimeout,
                             ), proxies=self._proxies
                        )
            obj = self._proccessResult(response.content)
    # 拋異常唬渗,連接超時
    except (requests.exceptions.ReadTimeout,requests.exceptions.ConnectTimeout) as e:
        return {
            'error_code': 'SDK108',
            'error_msg': 'connection or read data timeout',
        }

    return obj

3典阵、至此調用基本結束,接下來看里面用到的幾個方法:

  • ._auth()
def _auth(self, refresh=False):
    """
        api access auth镊逝,獲得access_token
    """

    #未過期
    if not refresh:
        # 設置超時時間為一個月
        tm = self._authObj.get('time', 0) + int(self._authObj.get('expires_in', 0)) - 30
        if tm > int(time.time()):
            return self._authObj
    # 如果access token過期壮啊,重新獲取,傳入?yún)?shù):grant_type蹋半,client_id他巨,client_secret和設置超時時間
    obj = self.__client.get(self.__accessTokenUrl, verify=False, params={
        'grant_type': 'client_credentials',
        'client_id': self._apiKey,
        'client_secret': self._secretKey,
    }, timeout=(
        self.__connectTimeout,
        self.__socketTimeout,
    ), proxies=self._proxies).json()

    self._isCloudUser = not self._isPermission(obj)
    obj['time'] = int(time.time())  # 按照當前時間重置access token超時時間
    self._authObj = obj

    return obj  # 返回認證過access token的對象
  • ._getParams(authObj)
# 得到的參數(shù)就是access_token,認證校驗傳輸都要攜帶
    def _getParams(self, authObj):
        """
            api request http url params
        """

        params = {}

        if self._isCloudUser == False:
            params['access_token'] = authObj['access_token']

        return params
  • ._proccessRequest(url, params, data, headers)
    def _proccessRequest(self, url, params, data, headers):
        """
            參數(shù)處理:在參數(shù)中加入語言减江、版本,比如python3
        """

        params['aipSdk'] = 'python'
        params['aipVersion'] = self.__version

        return data
  • ._getAuthHeaders('POST', url, params, headers)
    def _getAuthHeaders(self, method, url, params=None, headers=None):
        """
            api request http headers
        """

        headers = headers or {}
        params = params or {}

        if self._isCloudUser == False:  # 不是云端用戶捻爷,返回報頭
            return headers

        urlResult = urlparse(url)  # 解析路由
        for kv in urlResult.query.strip().split('&'):  # 對路由進行切分辈灼,取出有用的值把它賦給參數(shù)
            if kv:
                k, v = kv.split('=')
                params[k] = v

        # UTC timestamp,獲取時間戳也榄,主機號巡莹,版本等信息,保證唯一性
        timestamp = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
        headers['Host'] = urlResult.hostname
        headers['x-bce-date'] = timestamp
        version, expire = '1', '1800'

        # 1 Generate SigningKey
        # 拼接簽名鑰匙甜紫,使用hmac(HMAC是密鑰相關的哈希運算消息認證碼降宅,HMAC運算利用哈希算法,以一個密鑰和一個消息為輸入囚霸,生成一個消息摘要作為輸出)
        # 還要使用hashlib.sha256進行二次加密
        val = "bce-auth-v%s/%s/%s/%s" % (version, self._apiKey, timestamp, expire)
        signingKey = hmac.new(self._secretKey.encode('utf-8'), val.encode('utf-8'),
            hashlib.sha256
        ).hexdigest()

        # 2 Generate CanonicalRequest
        # 2.1 Genrate CanonicalURI
        canonicalUri = quote(urlResult.path)
        # 2.2 Generate CanonicalURI: not used here
        # 2.3 Generate CanonicalHeaders: only include host here

        canonicalHeaders = []
        for header, val in headers.items():
            canonicalHeaders.append(
                '%s:%s' % (
                    quote(header.strip(), '').lower(),
                    quote(val.strip(), '')
                )
            )
        canonicalHeaders = '\n'.join(sorted(canonicalHeaders))

        # 2.4 Generate CanonicalRequest
        canonicalRequest = '%s\n%s\n%s\n%s' % (
            method.upper(),
            canonicalUri,
            '&'.join(sorted(urlencode(params).split('&'))),
            canonicalHeaders
        )

        # 3 Generate Final Signature
        signature = hmac.new(signingKey.encode('utf-8'), canonicalRequest.encode('utf-8'),
                        hashlib.sha256
                    ).hexdigest()

        headers['authorization'] = 'bce-auth-v%s/%s/%s/%s/%s/%s' % (
            version,
            self._apiKey,
            timestamp,
            expire,
            ';'.join(headers.keys()).lower(),
            signature
        )

        return headers  # 最后頭部攜帶信息進行傳輸腰根,其中最重要的是signature,為此進行了兩次大加密拓型,大加密中又有兩次小加密额嘿。不得不說,重要信息在傳輸過程中一定要慎重A哟臁2嵫!
  • ._proccessResult(response.content)
    def _proccessResult(self, content):
        """
            formate result压固,格式化返回結果
        """

        if sys.version_info.major == 2:
            return json.loads(content) or {}
        else:
            return json.loads(content.decode()) or {}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末球拦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子帐我,更是在濱河造成了極大的恐慌坎炼,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焚刚,死亡現(xiàn)場離奇詭異点弯,居然都是意外死亡,警方通過查閱死者的電腦和手機矿咕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門抢肛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狼钮,“玉大人,你說我怎么就攤上這事捡絮“疚撸” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵福稳,是天一觀的道長涎拉。 經(jīng)常有香客問我,道長的圆,這世上最難降的妖魔是什么鼓拧? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮越妈,結果婚禮上季俩,老公的妹妹穿的比我還像新娘。我一直安慰自己梅掠,他們只是感情好酌住,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阎抒,像睡著了一般酪我。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上且叁,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天都哭,我揣著相機與錄音,去河邊找鬼谴古。 笑死质涛,一個胖子當著我的面吹牛,可吹牛的內容都是我干的掰担。 我是一名探鬼主播汇陆,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼带饱!你這毒婦竟也來了毡代?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤勺疼,失蹤者是張志新(化名)和其女友劉穎教寂,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體执庐,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡酪耕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了轨淌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迂烁。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡看尼,死狀恐怖,靈堂內的尸體忽然破棺而出盟步,到底是詐尸還是另有隱情藏斩,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布却盘,位于F島的核電站狰域,受9級特大地震影響,放射性物質發(fā)生泄漏黄橘。R本人自食惡果不足惜兆览,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望塞关。 院中可真熱鬧拓颓,春花似錦、人聲如沸描孟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匿醒。三九已至,卻和暖如春缠导,著一層夾襖步出監(jiān)牢的瞬間廉羔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工僻造, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留憋他,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓髓削,卻偏偏與公主長得像竹挡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子立膛,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內容