大家好,今天才哥带大家看看知乎这个高达14.3万关注,2.6亿浏览,回答数超过1.27万的问题《平常人可以漂亮到什么程度?》。

最近呢,可能是因为写了几篇关于爬虫获取美女照片的文章的缘故?总是收到知乎推送这个话题,由于关注才哥颜值得到蹭蹭上涨,现在终于敢点开这个问题,然后一探究竟啦!

注:全部代码、照片等数据,公众号后台回复“知乎”即可获取!

1. 预览

我们只将赞同数前100的回答中的照片进行对比,通过face++颜值评分接口获取的分值进行排序。

注:face++颜值评分不代表本人观点哈,感觉很多不是那个味道,哈哈。

以下是赞同数前三甲的答案中照片颜值评分最高的:

rank count score pic
1 57032 88.976
2 46551 87.644
3 27050 89.54

以下是颜值评分前三甲:

rank score pic
1 94.01
2 91.4
3 91.133

2. 数据采集

知乎的数据采集需要登录账号后才能看到,登录账号,点开目标网址:https://www.zhihu.com/question/50426133

2.1. 分析网页接口

常规流程:

  1. F12打开开发者模式—>Network—>XHR
  2. 下滑加载更多;
  3. 观测Name列变化,找到目标。

通过以上步骤,我们发现以下关键点:

在开发者模式中,我们发现limit默认为5,通过调试这个值可以发现最大可以设为20,也就是单页20条回答数据。

# 接口url地址
url = 'https://www.zhihu.com/api/v4/questions/50426133/answers?'
# 请求参数
parameters = {'include': 'data[*].is_normal,admin_closed_comment,reward_info,is_collapsed,annotation_action,annotation_detail,collapse_reason,is_sticky,collapsed_by,suggest_edit,comment_count,can_comment,content,editable_content,attachment,voteup_count,reshipment_settings,comment_permission,created_time,updated_time,review_info,relevant_info,question,excerpt,is_labeled,paid_info,paid_info_content,relationship.is_authorized,is_author,voting,is_thanked,is_nothelp,is_recognized;data[*].mark_infos[*].url;data[*].author.follower_count,badge[*].topics;data[*].settings.table_of_content.enabled','offset': page*20, # 未来的翻页变量在这里'limit': 20,'sort_by': 'default','platform': 'desktop',}

我们提到,需要登录获取cookie并传递给请求头才能正常请求到数据,这里可以在开发者模式中的Request Headers中获取到cookie值。

根据以上cookie值构建请求头参数:

# 请求头参数
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",'Cookie':'这里放你复制来的cookie咯'}

2.2. 基础数据请求

点开Preview,可以看到接口请求到的数据类型,我们发现是json数据,嗯。

最下面的totals是全部回答数量,每个回答的具体内容在data列表中。在第1步中,我们单页是20个回答数,因此可以构建总页数为 totals//20 +1

数据采集代码如下:

import requests
import re
import pandas as pd
import time
from tqdm import tqdmdef get_html(page):url = 'https://www.zhihu.com/api/v4/questions/50426133/answers?'parameters = {'include': 'data[*].is_normal,admin_closed_comment,reward_info,is_collapsed,annotation_action,annotation_detail,collapse_reason,is_sticky,collapsed_by,suggest_edit,comment_count,can_comment,content,editable_content,attachment,voteup_count,reshipment_settings,comment_permission,created_time,updated_time,review_info,relevant_info,question,excerpt,is_labeled,paid_info,paid_info_content,relationship.is_authorized,is_author,voting,is_thanked,is_nothelp,is_recognized;data[*].mark_infos[*].url;data[*].author.follower_count,badge[*].topics;data[*].settings.table_of_content.enabled','offset': page*20,'limit': 20,'sort_by': 'default','platform': 'desktop',}# 请求头参数headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",'Cookie':'这里放你复制来的cookie咯'}r = requests.get(url, params=parameters, headers=headers)return r# 获取首页数据,用于找回答数
r = get_html(0)
j = r.json()# 获取全部回答及总页数
totals = j['paging']['totals']
pages = totals//20 + 1# 获取全部回答详情
df_list = []
for page in tqdm(range(pages)):# 不限速爬虫会出现403的情况,加了之后发现没问题time.sleep(0.5)r = get_html(page)j = r.json()data = j['data']data_df = pd.DataFrame(data)# 选择需要的数据df = data_df[['id','type','answer_type','content', 'created_time', 'updated_time','voteup_count', 'comment_count']]df_list.append(df)
# 合并全部页数据
result = pd.concat(df_list)

回答内容预览:

2.3. 照片数据解析及下载

在请求的基础数据中,我们发现照片数据url地址藏在content中,而content数据格式有点像html文本,当然这里我们用re正则表达式进行解析哈。

html = '<p>是我见过最好看的地勤小姐姐。</p><p>在重庆机场。</p><figure><noscript><img src="https://pic1.zhimg.com/50/v2-3c6b1af3ed81a111115b60f9336ba4fd_hd.jpg?source=1940ef5c" data-rawwidth="960" data-rawheight="1280" class="origin_image zh-lightbox-thumb" width="960" data-original="https://pic1.zhimg.com/v2-3c6b1af3ed81a111115b60f9336ba4fd_r.jpg?source=1940ef5c"/></noscript><img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='960' height='1280'&gt;&lt;/svg&gt;" data-rawwidth="960" data-rawheight="1280" class="origin_image zh-lightbox-thumb lazy" width="960" data-original="https://pic1.zhimg.com/v2-3c6b1af3ed81a111115b60f9336ba4fd_r.jpg?source=1940ef5c" data-actualsrc="https://pic1.zhimg.com/50/v2-3c6b1af3ed81a111115b60f9336ba4fd_hd.jpg?source=1940ef5c"/></figure>'# 照片地址列表
img_urls = re.findall(r'<img src="(https:.*?)\?',html)

由于一共1.27万个回答,照片数更不知道有多少,我这里就不全部下载了,仅下载赞同数前100的回答里的照片啦。

# 按照赞同数降序
result.sort_values(by='voteup_count',ascending=False,inplace=True)
ids = result['id'].to_list()
htmls = result['content'].to_list()
m = n = 0
# for i , j in result[['id','content']].values:  # 亦可这样
# 爬取前100个回答中出现的照片
scores = []
for id_, html in zip(ids[:100], htmls[:100]):m = m+1img_urls = re.findall(r'<img src="(https:.*?)\?',html)for num,img_url in enumerate(img_urls):time.sleep(0.12)n = n + 1print(m, num+1, img_url)# 下载照片r_img = requests.get(img_url, headers=headers)           img = r_img.contentname = f'{m}-{id_}-{num+1}.jpg'# 写入本地with open(name,'wb') as f:f.write(img)print(f'共 {n}张 照片已经下载')

照片下载结果预览:

3. 性别分类及颜值评分

由于问题是《平常人可以漂亮到什么程度?》并没有指定性别,不过我们在爬取过程中发现绝大多数还是女性照片。为了更好的批量区分,我们可以在f调用ace++颜值评分接口时也带上性别即可。

在第2步中,我们其实已经知道了照片的url地址,这里只需要循环传入改地址即可。

# 定义获取评分的函数
def ksfaceScore(pic_url):url = 'https://api-cn.faceplusplus.com/facepp/v3/detect'APIKey = '你的key' APISecret = '你的secret'data = {"api_key":APIKey,"api_secret":APISecret,"image_url":pic_url,"return_attributes":"gender,age,beauty"}res = requests.post(url,data = data)dic_ = eval(res.text)try:gender = dic_['faces'][0]['attributes']['gender']['value']age = dic_['faces'][0]['attributes']['age']['value']beauty_w = dic_['faces'][0]['attributes']['beauty']['female_score']beauty_m = dic_['faces'][0]['attributes']['beauty']['male_score']except :gender=age=beauty_w=beauty_m = -1return gender,age,beauty_w,beauty_m# result = pd.read_csv(r'知乎问题-平常人可以漂亮到什么程度.csv',index_col=0)
result.sort_values(by='voteup_count',ascending=False,inplace=True)
ids = result['id'].to_list()
htmls = result['content'].to_list()
n = 0
m = 0
# for i , j in result[['id','content']].values:
# 爬取前100个回答中出现的照片
scores = []
for id_, html in zip(ids[:100], htmls[:100]):m = m+1img_urls = re.findall(r'<img src="(https:.*?)\?',html)for num,img_url in enumerate(img_urls):time.sleep(0.12)score = {}n = n + 1print(m, num+1, img_url)# 获取颜值评分gender,age,beauty_w,beauty_m = ksfaceScore(img_url)     score['gender'] = genderscore['age'] = agescore['beauty_w'] = beauty_w   score['beauty_m'] = beauty_mscore['name'] = id_score['url'] = img_urlscores.append(score)print(f'共 {n}张 照片已经完成颜值评分')df_score = pd.DataFrame(scores)

性别分类及颜值评分结果预览如下:

由于每个回答里存在多张照片,因为直接获取的结果里对同一个回答也是存在多条结果。

4. 数据处理

为了对每条回答指定唯一一条颜值评分数据,这里简单粗暴的采用取最大值的形式。

另外,为了和回答数据进行合并,我们需要通过唯一id的形式,而在颜值评分数据里对应的是字典name,其包含rank、id和page(指同一个回答里第page张照片),需要进行分列。

# 分列
df_score[['rank','id','page']]=df_score.name.str.split('-',2,expand=True)
# 分列后对id字典进行格式转化(转为为int)
df_score.id = df_score.id.astype('int')
# 按照 beauty_m 男性视角颜值评分 由大到小排序
df_score.sort_values(by='beauty_m',ascending=False,inplace=True)
# 按照 id分组,取第一个值也就是排序结果下的最大值
df_score = df_score.groupby('id').first().reset_index()

df_score处理后的结果预览:

合并:

top = pd.merge(df_score,result,how='left')
top = top[['id', 'gender', 'age', 'beauty_w', 'beauty_m', 'name', 'url', 'rank','page', 'type',  'voteup_count', 'comment_count']]

预览:

赞同数前三:

top.sort_values('voteup_count',ascending=False).head(3)

https://www.zhihu.com/question/50426133/answer/663160403
https://www.zhihu.com/question/50426133/answer/429332291
https://www.zhihu.com/question/50426133/answer/384888962

颜值评分前三:

top.sort_values('beauty_m',ascending=False).head(3)

https://www.zhihu.com/question/50426133/answer/417622373
https://www.zhihu.com/question/50426133/answer/490096144
https://www.zhihu.com/question/50426133/answer/487442393

补充一点,在数据采集时 关于 发布时间和更新时间两个字段是时间戳格式,可以通过以下方法转化为 我们所处时区的 时间:

# 时间戳改为日期时间格式
result['created_time'] = result['created_time'].apply(lambda x: pd.Timestamp(x, unit="s",tz='Asia/Shanghai'))
result['updated_time'] = result['updated_time'].apply(lambda x: pd.Timestamp(x, unit="s",tz='Asia/Shanghai'))

5. 数据统计与可视化

这部分仅针对全部回答基础数据进行简单的数据统计和可视化

5.1. 回答数时间分布

该问题是2016年9月7日被首次提出,不过直到2017年12月份才开始逐步热门起来,而在2018年该问题回答总数接近7000,成了大热门。

绘图代码:

import matplotlib.pyplot as plt
plt.rcParams['font.family'] = ['Microsoft YaHei'] #设置全局默认字体 为 幼圆
plt.rcParams['axes.unicode_minus'] = False # 解决中文字体下负号显示问题
plt.rcParams["axes.labelsize"] = 16  # 设置全局轴标签字典大小import seaborn as sns
sns.set_style("darkgrid",{"font.family":['Microsoft YaHei', 'SimHei']})   #seaborn绘图的字体设置plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号def plot_year(data,year):df = data[data['year']==year]plt.bar(df.month, df.回答数, color='lightpink')plt.title(year)for a, b in zip(df.month,df.回答数):plt.text(a, b+0.1, b, ha='center', va='bottom')plt.figure(figsize=(12,18), dpi=80)
plt.figure(1)
ax1 = plt.subplot(511)
plot_year(data,2016)
ax2 = plt.subplot(512)
plot_year(data,2017)
ax3 = plt.subplot(513)
plot_year(data,2018)
ax4 = plt.subplot(514)
plot_year(data,2019)
ax5 = plt.subplot(515)
plot_year(data,2020)

5.2. 赞同数与评论数关系

基本上赞同数和评论数正相关啦,简单做散点图如下:

df1 = df[(df['comment_count']>0)&(df['voteup_count']>0)]
plt.figure(figsize=(15,8))
plt.scatter(df1.comment_count,df1.voteup_count)

平常人可以漂亮到什么程度?教你爬取知乎大神们的回答一探究竟!相关推荐

  1. 手把手教你用Scrapy爬取知乎大V粉丝列表

    导读:通过获取知乎某个大V的关注列表和被关注列表,查看该大V以及其关注用户和被关注用户的详细信息,然后通过层层递归调用,实现获取关注用户和被关注用户的关注列表和被关注列表,最终实现获取大量用户信息. ...

  2. python爬取二手房信息_刚刚接触PythonR?教你爬取分析赶集网北京二手房数据(附详细代码)...

    原标题:刚刚接触Python&R?教你爬取分析赶集网北京二手房数据(附详细代码) 源 /数据森麟文 /徐涛 前言: 本文主要分为两部分:Python爬取赶集网北京二手房数据&R对爬取的 ...

  3. 【爬虫】Yhen手把手教你爬取表情包,让你成为斗图界最靓的仔!

    以下内容为本人原创,欢迎大家观看学习,禁止用于商业用途,转载请说明出处,谢谢合作! ·作者:@Yhen ·原文网站:CSDN ·原文链接:https://blog.csdn.net/Yhen1/art ...

  4. python 批量下载网页图片_手把手教你爬取天堂网1920*1080大图片(批量下载)——实战篇|python基础教程|python入门|python教程...

    https://www.xin3721.com/eschool/pythonxin3721/ /1 前言/ 上篇文章 手把手教你爬取天堂网1920*1080大图片(批量下载)--理论篇我们谈及了天堂网 ...

  5. 100行代码教你爬取斗图网(Python多线程队列)

    100行代码教你爬取斗图网(Python多线程队列) 前言 根据之前写的两篇文章,想必大家对多线程和队列有了一个初步的了解,今天这篇文章就来实战一下,用多线程 + 队列 爬取斗图网的全网图片. 你还在 ...

  6. 手把手教你爬取PC端『某酷视频』个人历史播放数据,并可视化展示

    大家好,我是阿辰,今天手把手教你爬取PC端『某酷视频』个人历史播放数据,并可视化展示 上次有粉丝说,那个是ios手机,安卓手机现在需要root权限才可以安装证书,那么今天就不以手机为例,以电脑PC端为 ...

  7. 手把手教你爬取清纯小姐姐私房照,小孩子写学

    手把手教你爬取清纯小姐姐私房照,小孩子写学 先上效果图 头文件: 因为爬虫需要用到请求网络部分,所以需要这两个包,没有的话自行下载即可.这个可以直接用pip安装.如果连pip都不懂,那就只能学习一下p ...

  8. 猫眼html源码,50 行代码教你爬取猫眼电影 TOP100 榜所有信息

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 今天,手把手教你入门 Python 爬虫,爬取猫眼电影 TOP100 榜信息. 作者 | 丁 ...

  9. 50 行代码教你爬取猫眼电影 TOP100 榜所有信息

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 今天,手把手教你入门 Python 爬虫,爬取猫眼电影 TOP100 榜信息. 作者 | 丁 ...

最新文章

  1. 开会迟到,代码不规范,晚上八点半去健身,跟leader坐电梯自己先出去!某新入行程序员被疯狂吐槽!...
  2. SpaceX再发射58颗星链卫星 总数达到538颗
  3. 专访趋势科技CEO陈怡桦:病毒行业需要反省
  4. vs code golang代码自动补全
  5. 一文搞懂mysql:mysql学习目录链接大全
  6. linux emule 编译 wx-config --libs,LeezPi-RK3399_Android9编译说明
  7. 钱线观察:货币基金T+0驾到 活期存款将死?
  8. [AX]AX2012 SSRS报表使用Report Data Method
  9. java listen_JavaWeb之Filter、Listener
  10. Effective Java学习笔记之第6条 消除过期的引用对象
  11. 快速查找对方IP地址经典技巧汇总
  12. 药品管理系统java_基于Java的药品管理系统
  13. java2wsdl_Java2WSDL之java实现
  14. 基于语音识别的智能垃圾分类控制系统设计
  15. R语言之dpqr概率函数
  16. 网易的爆款密码,藏在Q3财报里
  17. Linux下Qt窗口半透明,Qt实现嵌入桌面的半透明窗口 good
  18. 数据研究必备:国内40个免费数据源大放送!
  19. 云计算大行其道 变革传统IT服务
  20. 2022 hgame creakme

热门文章

  1. 关于 分布式和微服务 的一些总结
  2. VBA操作Excel
  3. html+css实现3D相册
  4. Redis集群技术架构
  5. 全面认识海思SDK及嵌入式层开发(3)
  6. Mysql之更新数据_UPDATE
  7. 51单片机对I2C总线上挂接多个AT24C02的读写操作+Proteus仿真
  8. 11.22A 御坂美琴-优先队列模拟
  9. android scaletype没作用,Android ImageView 的scaleType 属性图解
  10. 手机上pdf转换成word怎么转