Python实现知乎高颜值图片自动化爬取与人脸检测
本文详细介绍如何使用Python编写爬虫程序,通过知乎开放API获取话题下的回答列表,并利用百度云人脸检测接口对图片进行颜值评分。教程涵盖环境配置、API调用、反爬策略处理及图片保存逻辑,帮助开发者实现自动化筛选高颜值图片的功能。
环境依赖与库导入
首先,需要导入程序运行所需的各类依赖库。这包括用于时间控制的时间模块、处理数据结构的pydash、进行Base64编码的base64模块、发起网络请求的requests库、解析HTML内容的lxml库中的etree、调用百度云人脸检测服务的AipFace类,以及用于处理文件路径的pathlib模块。
import time
import pydash
import base64
import requests
from lxml import etree
from aip import AipFace
from pathlib import Path
百度云API配置与认证
接下来,必须配置百度云人脸检测服务的认证信息。这是程序运行的核心前提,需填写APP_ID、API_KEY和SECRET_KEY这三个关键参数。此外,还需设定颜值过滤阈值BEAUTY_THRESHOLD,数值越高筛选越严格,可根据存储空间调整。同时,需要配置AUTHORIZATION令牌,该令牌可从浏览器开发者工具中复制,建议使用个人账号生成的令牌以避免因多人共用同一令牌触发知乎反爬机制而影响程序运行。
#唯一必须填的信息就这三行
APP_ID = "xxxxxxxx"
API_KEY = "xxxxxxxxxxxxxxxx"
SECRET_KEY = "xxxxxxxxxxxxxxxx"
# 过滤颜值阈值,存储空间大的请随意
BEAUTY_THRESHOLD = 55
AUTHORIZATION = "oauth c3cef7c66a1843f8b3a9e6a1e3160e20"
# 如果权限错误,浏览器中打开知乎,在开发者工具复制一个,无需登录
# 建议最好换一个,因为不知道知乎的反爬虫策略,如果太多人用同一个,可能会影响程序运行
爬虫参数设定
以下配置项通常无需修改,但需了解其含义。LIMIT参数定义了每次请求知乎讨论列表时获取的数据条数,建议保持较小数值以符合规范。SOURCE参数指定了目标话题ID,此处使用“美女”话题(ID: 19552207),它是“颜值”话题(ID: 20013528)的父话题,用于确定数据源范围。
# 每次请求知乎的讨论列表长度,不建议设定太长,注意节操
LIMIT = 5
# 这是话题『美女』的 ID,其是『颜值』(20013528)的父话题
SOURCE = "19552207"
请求头与API接口构建
为了模拟正常浏览器的访问行为,需设置User-Agent和Referer请求头。User-Agent模拟Windows系统下的Safari浏览器,Referer指向知乎特定话题的新增内容页面。BASE_URL定义了获取话题下时间线活动的基础接口地址,URL_QUERY则包含了复杂的请求参数,用于筛选特定类型的数据(如回答、文章等)并指定返回字段,最后拼接LIMIT参数以控制返回数量。HEADERS字典汇总了上述请求头信息,用于后续所有HTTP请求。
USER_AGENT = "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.5 Safari/534.55.3"
REFERER = "https://www.zhihu.com/topic/%s/newest" % SOURCE
# 某话题下讨论列表请求 url
BASE_URL = "https://www.zhihu.com/api/v4/topics/%s/feeds/timeline_activity"
# 初始请求 url 附带的请求参数
URL_QUERY = "?include=data%5B%3F%28target.type%3Dtopic_sticky_module%29%5D.target.data%5B%3F%28target.type%3Danswer%29%5D.target.content%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%3Bdata%5B%3F%28target.type%3Dtopic_sticky_module%29%5D.target.data%5B%3F%28target.type%3Danswer%29%5D.target.is_normal%2Ccomment_count%2Cvoteup_count%2Ccontent%2Crelevant_info%2Cexcerpt.author.badge%5B%3F%28type%3Dbest_answerer%29%5D.topics%3Bdata%5B%3F%28target.type%3Dtopic_sticky_module%29%5D.target.data%5B%3F%28target.type%3Darticle%29%5D.target.content%2Cvoteup_count%2Ccomment_count%2Cvoting%2Cauthor.badge%5B%3F%28type%3Dbest_answerer%29%5D.topics%3Bdata%5B%3F%28target.type%3Dtopic_sticky_module%29%5D.target.data%5B%3F%28target.type%3Dpeople%29%5D.target.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F%28type%3Dbest_answerer%29%5D.topics%3Bdata%5B%3F%28target.type%3Danswer%29%5D.target.content%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%3Bdata%5B%3F%28target.type%3Danswer%29%5D.target.author.badge%5B%3F%28type%3Dbest_answerer%29%5D.topics%3Bdata%5B%3F%28target.type%3Darticle%29%5D.target.content%2Cauthor.badge%5B%3F%28type%3Dbest_answerer%29%5D.topics%3Bdata%5B%3F%28target.type%3Dquestion%29%5D.target.comment_count&limit=" + str(
LIMIT)
HEADERS = {
"User-Agent": USER_AGENT,
"Referer": REFERER,
"authorization": AUTHORIZATION
图片数据获取函数
定义获取图片原始内容的函数fetch_image。该函数接收图片URL作为参数,使用之前定义的HEADERS发送GET请求。若请求过程中发生异常,则抛出错误;若成功,则返回图片的二进制内容(response.content),以便后续处理或保存。
def fetch_image(url):
try:
response = requests.get(url, headers=HEADERS)
except Exception as e:
raise e
return response.content
话题列表数据获取函数
定义获取话题列表JSON数据的函数fetch_activities。该函数接收API接口URL,同样使用HEADERS发送GET请求。成功时返回解析后的JSON对象,失败时抛出异常。此函数用于从知乎API获取包含回答、文章等内容的结构化数据。
def fetch_activities(url):
try:
response = requests.get(url, headers=HEADERS)
except Exception as e:
raise e
return response.json()
数据处理、颜值检测与图片保存
定义处理返回数据并执行颜值检测与保存的函数parser_activities。该函数遍历数据列表中的每一项,检查目标对象是否包含content、question和author字段,若缺失则跳过。通过etree解析HTML内容,提取所有img标签的src属性。对每个以http开头的图片链接,调用fetch_image获取数据,并传入face_detective进行颜值检测。若检测结果有效,则生成包含颜值分数、作者名、标题和序号的文件名,并在指定目录下保存为jpg文件。每次保存后暂停2秒以避免请求过快。若数据分页未结束,则返回下一页URL继续处理;否则返回None表示结束。
def parser_activities(datums, face_detective):
for data in datums["data"]:
target = data["target"]
if "content" not in target or "question" not in target or "author" not in target:
continue
html = etree.HTML(target["content"])
seq = 0
title = target["question"]["title"]
author = target["author"]["name"]
images = html.xpath("//img/@src")
for image in images:
if not image.startswith("http"):
continue
image_data = fetch_image(image)
score = face_detective(image_data)
if not score:
continue
name = "{}--{}--{}--{}.jpg".format(score, author, title, seq)
seq = seq + 1
path = Path(__file__).parent.joinpath("image").joinpath(name)
try:
f = open(path, "wb")
f.write(image_data)
f.flush()
f.close()
print(path)
time.sleep(2)
except Exception as e:
continue
if not datums["paging"]["is_end"]:
return datums["paging"]["next"]
else:
return None
人脸检测工具初始化
初始化颜值检测工具函数init_detective。该函数接收百度云API的ID和密钥,创建AipFace客户端实例。配置options指定检测字段包括年龄、性别、颜值和特质。内部定义detective函数,接收图片二进制数据,将其转换为Base64字符串后调用client.detect方法。从响应中提取result,若未返回结果或人脸数量为0则返回None。检查第一张脸的概率是否低于0.6,若是则跳过。进一步检查颜值分数是否低于预设阈值BEAUTY_THRESHOLD,若是则跳过。最后确认性别是否为女性,若符合所有条件,则返回该脸的颜值分数;否则返回None。最终返回detective函数供主程序调用。
def init_detective(app_id, api_key, secret_key):
client = AipFace(app_id, api_key, secret_key)
options = {"face_field": "age,gender,beauty,qualities"}
def detective(image):
image = str(base64.b64encode(image), "utf-8")
response = client.detect(str(image), "BASE64", options)
response = response.get("result")
if not response:
return
if (not response) or (response["face_num"] == 0):
return
face_list = response["face_list"]
if pydash.get(face_list, "0.face_probability") < 0.6:
return
if pydash.get(face_list, "0.beauty") < BEAUTY_THRESHOLD:
return
if pydash.get(face_list, "0.gender.type") != "female":
return
score = pydash.get(face_list, "0.beauty")
return score
return detective
程序主流程控制
定义程序主入口函数main。首先调用init_detective初始化人脸检测工具,传入之前配置的APP_ID、API_KEY和SECRET_KEY。接着构建完整的API请求URL,由BASE_URL、SOURCE和URL_QUERY拼接而成。进入while循环,只要url不为None,就调用fetch_activities获取数据,并调用parser_activities处理数据并获取下一页URL。每次循环结束后暂停5秒,以控制请求频率。最后,在标准入口判断中调用main函数执行整个流程。
def main():
face_detective = init_detective(APP_ID, API_KEY, SECRET_KEY)
url = BASE_URL % SOURCE + URL_QUERY
while url is not None:
datums = fetch_activities(url)
url = parser_activities(datums, face_detective)
time.sleep(5)
if __name__ == '__main__':
main()
总结
本文完整展示了利用Python爬虫技术结合百度云人脸检测接口,自动化抓取并筛选知乎高颜值图片的实现过程。希望本文的内容能为读者的学习和实践提供参考,欢迎大家继续支持本站获取更多技术分享。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









