一、程序说明
1.1 程序说明
之前写调用百度AI接口的程序,然后刷到了两条明星的新闻,就想到了写个给明星颜值排下名的程序。
程序的关键点是两个,第一个是百度AI接口的调用这点其实直接使用早前实现的类所以没有费什么劲(见Python3+BaiduAI识别高颜值妹子图片)。
第二个是怎么个排法,这个问题还比较大可以分成几个点,第一点是排哪些明星,有哪些明星我也不是很清楚就随便百度一下然后用了这个网站的名单:https://123fans.cn/rank.php?c=2
第二个点是去哪里取图片,开始想的是从百度异步加载图片接口取图片但是发现百度用了一些防止这种操作的措施返回的结果列表直接访问会返回403,再分析一阵应该可以处理上selenium硬刚应该也可以但是没必要,换用了搜狗的。结果看到排第一的是范女皇,又加了一个360的排名有了些变化但总的排第一的还是范女皇。第一就第一吧我也不那么在意。
所以现的程序流程就是:从一个网页中取回明星名单----for循环名单列表----到搜狗和360各取一次ajax(大概各40张)----将每张图片传到百度AI接口----获取AI接口评分存入数据库。
1.2 程序结果说明
百度AI评分排行前99名:
百度AI评分最高二十张图片(AI思想出了问题,慎点):
方数真----97.77404785----sougou----http://s4.sinaimg.cn/mw690/001TftpDzy6JKwGUAAb33&690
陈紫函----97.15953064----360----http://images.rednet.cn/articleimage/2010/10/12/1129069853.jpg
杨幂----96.82311249----sougou----http://img5q.duitang.com/uploads/item/201505/12/20150512211001_5uvdh.jpeg
甘婷婷----96.7035675----360----http://s10.sinaimg.cn/mw690/5330f076gd6c34d9b4a29&690
张馨予----96.45571899----sougou----http://s8.sinaimg.cn/mw690/001AxaSkgy6VfYILP3pa7&690
孟子义----96.44942474----360----http://upload.qianhuaweb.com/2016/0830/1472529588682.jpg
范冰冰----95.78607178----sougou----http://p5.qhimg.com/t01d29f433bf172993e.png
张萌----95.58099365----sougou----http://himg2.huanqiu.com/attachment2010/2017/0219/20170219021506253.jpg
杨子姗----95.5355835----sougou----http://www.marubi.cn/vancheerfile/images/2017/3/2017030809597975.jpg
穆婷婷----95.47248077----sougou----http://img.cechoice.com/2016/03/24/201603241349he6ke.500x749.jpg
穆婷婷----95.35915375----sougou----http://img.cechoice.com/2016/03/24/201603241355gd6jd.500x749.jpg
范冰冰----95.2871933----360----http://pic16.nipic.com/20110915/8042943_090150767000_2.jpg
张萌----95.12875366----sougou----http://s8.sinaimg.cn/mw690/0041rhFZzy768ajttf927&690
蒋梦婕----94.87149048----360----http://img1.gtimg.com/ent/pics/hv1/52/109/1370/89112097.jpg
杨幂----94.79195404----sougou----http://cdn.duitang.com/uploads/item/201510/06/20151006152520_Eca3e.jpeg
赵丽颖----94.52903748----360----http://pic1.win4000.com/wallpaper/a/51a845cf17335.jpg
杨幂----94.52243042----360----http://img4.guang.j.cn/g5/M02/C7/76/wKghslZ_uXLT9fwLAADH7H3o2kY14.jpeg!q.50
江语晨----94.43437958----sougou----http://www.ttpaihang.com/image/vote/20111107092812512110.jpg
陈紫函----94.32379913----360----http://news.youth.cn/yl/201307/W020130726332937171156.jpg
江疏影----94.25344086----sougou----http://img0.ph.126.net/8s_MG7gI11mRTMu2W0MGiA==/6631915489163583882.jpg
二、程序源码
主程序源代码(beauty_rank.py):
import time import json import logging import sqlite3 import requests from lxml import etree from urllib.parse import quote from BaiduFaceIdentify import BaiduFaceIdentify class BeautyRank(): def __init__(self): self.db_conn = sqlite3.connect('beauty_rank.db') self.db_cursor = self.db_conn.cursor() self.model_count = 0 self.bfi = BaiduFaceIdentify() pass def request_name_list_url(self,name_list_url): headers = { 'Host': '123fans.cn', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'Accept-Encoding': 'gzip, deflate, br', 'Referer': 'https://www.ugirls.com/Models/', } # 访问明星名单url response = requests.get(name_list_url,headers=headers,timeout=10) if response.status_code != 200: logging.warning(f"请求失败:{response.status_code}") return False sel = etree.HTML(response.text) # 获取明星名单列表 name_lists = sel.xpath('//div[@id="main"]//div[@class="ranking"]//td[@class="name"]//a/text()') star_counts = len(name_lists) count = 0 # 遍历明星名单 for star_name in name_lists: count += 1 try: logging.warning(f' 开始采集{count}/{star_counts}:{star_name}') # 通过搜狗获取明星图片 self.request_and_parse_star_img(star_name,'sougou') # 通过360获取明星图片 self.request_and_parse_star_img(star_name,'360') except: logging.warning(f' {count}/{star_counts}:{star_name}出现错误') continue def request_and_parse_star_img(self, star_name, search_engine): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'X-Requested-With': 'XMLHttpRequest', 'Connection': 'close', } # 根据要求使用的搜索引擎构建请求的url和完善头部信息 if search_engine == 'sougou': star_img_ajax_request_url = f'http://pic.sogou.com/pics?query={quote(star_name)}&mode=1&start=96&reqType=ajax&reqFrom=result&tn=0' headers['Host'] = 'pic.sogou.com' headers['Referer'] = 'http://pic.sogou.com/pics?ie=utf8&p=40230504&interV=kKIOkrELjboMmLkEk7kTkKILlLELjboLmLkEkrgTkKIMkrELjboImLkEk74TkKILmrELjb8TkKIKmrELjbkI_1093829215&query=%E8%B5%B5%E4%B8%BD%E9%A2%96&' # 下边从json_results中抽取明星图片列表的key name img_frames_key = 'items' # 下边从明星图片中抽取图片具体url的key name img_url_key = 'pic_url' elif search_engine == '360': star_img_ajax_request_url = f'http://image.so.com/j?q={quote(star_name)}&src=tab_www&correct={quote(star_name)}&pn=60&ch=&sn=120&sid=af5aac1212d41c3b5cd6a96a0c311ba2&ran=0&ras=0&cn=0&gn=10&kn=50' headers['Host'] = 'image.so.com' headers['Referer'] = 'http://image.so.com/i?q=%E8%B5%B5%E4%B8%BD%E9%A2%96&src=tab_www' img_frames_key = 'list' img_url_key = 'img' # 访问搜索引擎,获取明星图片url try: response = requests.get(star_img_ajax_request_url, headers=headers, timeout=10) if response.status_code != 200: logging.warning('请求出错:%s' % response.status_code) return False json_results = json.loads(response.text) except: return False # 遍历图片列表,调用百度AI接口并接收图片颜值 for img_frame in json_results[img_frames_key]: img_url = img_frame[img_url_key] logging.warning(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}开始识别:{img_url}') try: beauty_value = self.bfi.parse_face_pic(img_url) except: logging.warning('百度识别出现错误') continue # 如果颜值没有问题则插入数据库 if beauty_value > 1.0: logging.warning( f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}即将插入数据库({search_engine}):{star_name}-{beauty_value}-{img_url}') self.insert_into_database(star_name, beauty_value, img_url,search_engine) return True # 此函数用于将结果插入数据库 def insert_into_database(self,star_name,beauty_value,img_url,search_engine): # 如果表star_beauty_value不存在则先创建 sql = '''create table if not exists star_beauty_value(star_name text,beauty_value int,img_url text,search_engine text)''' self.db_cursor.execute(sql) self.db_conn.commit() # 将结果插入数据库 sql = f'''insert into star_beauty_valuex values('{star_name}','{beauty_value}','{img_url}','{search_engine}')''' self.db_cursor.execute(sql) self.db_conn.commit() def __del__(self): self.db_cursor.close() self.db_conn.close() pass if __name__ == '__main__': # 明星名单url name_list_url = 'https://123fans.cn/rank.php?c=2' # 实例化 beauty_rank = BeautyRank() beauty_rank.request_name_list_url(name_list_url)
百度AI图像识别接口调用代码(BaiduFaceIdentify.py):
import base64 import requests import json import logging import time class BaiduFaceIdentify(): #此函数用于获取access_token,返回access_token的值 #此函数被parse_face_pic调用 def get_access_token(self): client_id = 'KuLRFhTzX3zBFBSrbQBsl6Q4' #此变量赋值成自己API Key的值 client_secret = '8ahbIb2hEOePzXhehw9ZDL9kGvbzIHTU' #此变量赋值成自己Secret Key的值 auth_url = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + client_id + '&client_secret=' + client_secret response_at = requests.get(auth_url,timeout=10) json_result = json.loads(response_at.text) access_token = json_result['access_token'] return access_token #此函数进行人脸识别,返回识别到的人脸列表 #此函数被parse_face_pic调用 def identify_faces(self,url_pic,url_fi): headers = { 'Content-Type': 'application/json; charset=UTF-8' } # 因为提交URL让baidu去读取图片,总是返回图片下载错了 # 所以我们这里将读取URL指向的图片,将图片转成BASE64编码,改用提交BASE64编码而不是提交URL # pic_obj = urllib.request.urlopen(url_pic) # pic_base64 = base64.b64encode(pic_obj.read()) response = requests.get(url_pic,timeout=10) pic_base64 = base64.b64encode(response.content) post_data = { # 'image': url_pic, # 'image_type' : 'URL', 'image': pic_base64, 'image_type': 'BASE64', 'face_field': 'facetype,gender,age,beauty', #expression,faceshape,landmark,race,quality,glasses 'max_face_num': 1 } logging.warning(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}即将识别b2:{url_pic}') response_fi = requests.post(url_fi,headers=headers,data=post_data,timeout=10) json_fi_result = json.loads(response_fi.text) # 有些图片是没有人脸的,或者识别有问题,这个我们不细管直接捕获异常就返回空列表 try: # if json_fi_result['result'] is None: # return [] # else: return json_fi_result['result']['face_list'] except Exception: return [] #下边的print也许是最直观,你最想要的 #print(json_fi_result['result']['face_list'][0]['age']) #print(json_fi_result['result']['face_list'][0]['beauty']) #此函数用于解析进行人脸图片,返回图片中人物颜值 #此函数调用get_access_token、identify_faces def parse_face_pic(self,url_pic): #调用get_access_token获取access_token access_token = self.get_access_token() # access_token = '24.69a8b9206b4989703e38f4fb92878127.2592000.1534075146.282335-11407672' url_fi = 'https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=' + access_token #调用identify_faces,获取人脸列表 logging.warning(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}开始识别b1:{url_pic}') json_faces = self.identify_faces(url_pic,url_fi) # 如果没有人脸,那么就以0.0为颜值评分返回 if len(json_faces) == 0: # logging.warning('未识别到人脸') return 0.0 else: for json_face in json_faces: logging.debug('种类:'+json_face['face_type']['type']) logging.debug('性别:'+json_face['gender']['type']) logging.debug('年龄:'+str(json_face['age'])) logging.debug('颜值:'+str(json_face['beauty'])) # 如果识别到的不是妹子,也以1.0为颜值评分返回 # 如果识别到的是妹子,直接以值颜值返回 if json_face['gender']['type'] != 'female': # logging.info('图片不是妹子') return 1.0 else: return json_face['beauty'] if __name__ == '__main__': #uil_pic赋值成自己要测试的图片的url地址 url_pic = 'http://pic.ikafan.com/imgp/L3Byb3h5L2h0dHAvdXNlcmltYWdlMy4zNjBkb2MuY29tLzEzLzA1MDkvMDUvNjYyMjAxMF8yMDEzMDUwOTA1Mzk0NjA4MDMuanBn.jpg' bfi = BaiduFaceIdentify() bfi.parse_face_pic(url_pic)