对于很多人来说,拥有一个漂亮的女朋友是一件非常幸福的事情。知乎上就有一个非常热门的话题,叫做有个漂亮女朋友是种怎样的体验?在知乎上阅读量已经达到了5亿的阅读量,受到了十万多人的关注。


其实皮囊和灵魂两个词汇往往对应着喜欢和爱两个字眼,漂亮的女朋友值得夸耀,但是好看的皮囊下灵魂是否也像外在那么纯粹自然这才是重中之重,所以漂亮不该那么狭义,所以漂亮应该漂亮的通透。


那么别人的女朋友到底是什么样子呢,忍不住好奇心的我研究了下,想看看别人的女朋友是可盐可甜呢,还是清纯动人,或者是长相甜美,于是我爬取了评论区所有的图片,把这个问题下所有回答下的图片下载到我的电脑里面一探究竟。


原理其实蛮简单的,因为之前就知道知乎有个api一直可以用:

https://www.zhihu.com/node/QuestionAnswerListV2


这样的话,我们只需要构建相应的post参数即可获取了,构建的参数,我们只需要知道对应的问题ID即可,然后在把参数给构建成如下这种形式:

postdata = {'method': 'next','params': '{"url_token":' + str(qid) + ',"pagesize": "10","offset":' + str(offset) + "}"}


构建完参数后,我们直接发送请求,就可以获取对应的json数据,然后用正则表达式提取每个回答下的所有图片链接就OK了。


其次在转换json的时候,小编为了省事使用的是eval函数,不太建议,至于为什么不建议,自己可百度下eval函数的用法,可根据自己的情况自行修改。


爬虫代码如下:

# coding:utf-8
# __auth__ = "maiz"
# __date__ = "2021/4/3"
import re
import requests
import os
import urllib.request
import ssl


from urllib.parse import urlsplit
from os.path import basename


# 全局禁 用证书验证
ssl._create_default_https_context = ssl._create_unverified_context


headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36",
'Accept-Encoding': 'gzip, deflate'
}


# 下载出错的列表
failed_image_list = []




def mkdir(path):
if not os.path.exists(path):
print('新建文件夹:', path)
os.makedirs(path)
return True
else:
print(u"图片存放于:", os.getcwd() + os.sep + path)
return False




def download_pic2(img_lists, dir_name):
print("一共有{num}张照片".format(num=len(img_lists)))


# 标记下载进度
index = 1


for image_url in img_lists:
file_name = dir_name + os.sep + basename(urlsplit(image_url)[2])


# 已经下载的文件跳过
if os.path.exists(file_name):
print("文件{file_name}已存在。".format(file_name=file_name))
index += 1
continue


# 重试次数
retry_time = 3
auto_download(image_url, file_name, retry_time)


print("下载{pic_name}完成!({index}/{sum})".format(pic_name=file_name, index=index, sum=len(img_lists)))
index += 1


# 打印下载出错的文件
if len(failed_image_list):
print("以下文件下载失败:")
for failed_image_url in failed_image_list:
print(failed_image_url)




def auto_download(image_url, file_name, retry_time):
# 递归下载,直到文件下载成功
try:
# 判断剩余下载次数是否小于等于0,如果是,就跳过下载
if retry_time <= 0:
print("下载失败,请检查{image_url}链接是否正确(必要时可以手动下载)")
failed_image_list.append(image_url)
return


# 下载文件
urllib.request.urlretrieve(image_url, file_name)


except urllib.request.ContentTooShortError:
print("文件下载不完整,尝试重新下载,剩余尝试次数{retry_time}".format(retry_time=retry_time))
retry_time -= 1
auto_download(image_url, file_name, retry_time)


except urllib.request.URLError as e:
print("网络连接出错,尝试重新下载,剩余尝试次数{retry_time}".format(retry_time=retry_time))
retry_time -= 1
auto_download(image_url, file_name, retry_time)




def download_pic(img_lists, dir_name):
print("一共有{num}张照片".format(num=len(img_lists)))
for image_url in img_lists:
response = requests.get(image_url, stream=True)
if response.status_code == 200:
image = response.content
else:
continue


file_name = dir_name + os.sep + basename(urlsplit(image_url)[2])


try:
with open(file_name, "wb") as picture:
picture.write(image)
except IOError:
print("IO Error\n")
continue
finally:
picture.close()


print("下载{pic_name}完成!".format(pic_name=file_name))




def get_image_url(qid, headers, path):
# 利用正则表达式把源代码中的图片地址过滤出来
# reg = r'data-actualsrc="(.*?)">'
tmp_url = "https://www.zhihu.com/node/QuestionAnswerListV2"
offset = 0
image_urls = []


session = requests.Session()


# 答案数
answer_num = 0


while True:
postdata = {'method': 'next',
'params': '{"url_token":' + str(qid) + ',"pagesize": "10","offset":' + str(offset) + "}"}
page = session.post(tmp_url, headers=headers, data=postdata)
ret = eval(page.text)
answers = ret['msg']


offset += 10


if not answers:
print("图片URL获取完毕, 页数: ", (offset - 10) / 10)
return image_urls


answer_num += len(answers)


# reg = r'https://pic\d.zhimg.com/[a-fA-F0-9]{5,32}_\w+.jpg'
imgreg = re.compile('data-original="(.*?)"', re.S)


for answer in answers:
tmp_list = []
url_items = re.findall(imgreg, answer)


for item in url_items: # 这里去掉得到的图片URL中的转义字符'\\'
image_url = item.replace("\\", "")
tmp_list.append(image_url)


# 清理掉头像和去重 获取data-original的内容
tmp_list = list(set(tmp_list)) # 去重
for item in tmp_list:
if item.endswith('r.jpg'):
print(item)
write_image_url_to_file(path, item)
image_urls.append(item)


print('offset: %d, num : %d' % (offset, len(image_urls)))


# 打印答案数
print(u"答案数:%d" % (len(answers)))




def write_image_url_to_file(file_name, image_url):
file_full_name = file_name + '.txt'


f = open(file_full_name, 'a')
f.write(image_url + '\n')
f.close()




def read_image_url_from_file(file_name):
file_full_name = file_name + '.txt'


# 文件下载链接列表
image_url_list = []


# 判断文件是否存在
if not os.path.exists(file_full_name):
return image_url_list


with open(file_full_name, 'r') as f:
for line in f:
line = line.replace("\n", "")
image_url_list.append(line)


print("从文件中读取下载链接完毕,总共有{num}个文件".format(num=len(image_url_list)))
return image_url_list




if __name__ == '__main__':
title = '你们身边有什么素人美女吗?'
question_id = 406321189
zhihu_url = "https://www.zhihu.com/question/{qid}".format(qid=question_id)
path = str(question_id) + '_' + title
mkdir(path) # 创建本地文件夹


# 优先从文件中读取下载列表
img_list = read_image_url_from_file(path)
if not len(img_list):
# 获取图片的地址列表
img_list = get_image_url(question_id, headers, path)


# 下载文件
download_pic2(img_list, path)


右击运行代码,即可在本地生成一个文件夹,里面下载的都是下载后的评论区的图片。代码获取后台回复:”知乎评论图片“。


既然图片都可以获取到,那么评论区的其他信息就不用多说了吧,这个可以根据你自己的水平自由的发挥。


以上就是今天给大家分享的内容,更多精品教程请关注公众号SpiderBy,回复“Python教程”,即可获取*智基础+就业班课程。