刚学爬虫时,看到一篇文章硬核破解知乎登陆,心潮澎湃,真男人!符合我的胃口!哼哧哼哧的立刻安排!
(半个小时过后)
似乎我是弱智?很多看不懂?(百度乱搜中…)恩还有种简单的?selenium
+xpath
模拟登陆?简单但效率低?难道要靠用这种低效率方式来爬取数据,这是向网站妥协!不,我常威就算没技术也绝对不要这样委屈求全!(十分钟过后)挨,怎么他喵这么香?
经过一番曲折的故事(中间花了半个月拿了几个小项目练练手),终于进入激动人心的实战,马上就可以 爬取知乎姑娘的美照 学到新知识了!本文行文结构如下:
1. 做好准备了吗
2. selenium
+xpath
模拟登陆知乎获取cookies
3. request
+re
+json
+jsonpath
爬取知乎指定问题下所有回答数据(照片)
4. 进行面对对象重新构造
5. 总结
selenium 安装配置教程
selenium
及相应环境驱动配置安装,请查看:
selenium及驱动器安装配置教程详解
什么是selenium
不知道大家有没有用过按键精灵的API,用这套API我们就可以进行点击、输入等一系列模拟真实用户操作。selenium和其类似,只不过它可直接作用于浏览器,模拟打开、进行点击,输入等操作。用它可以很方便避开反爬机制,拿到我们要的界面源码进而获取数据,但是缺点速度太慢。
了解更多:
Python爬虫利器五之Selenium的用法
Python 爬虫基础Selenium库的使用
什么是xpath
前面我们介绍过正则表达式和相应re
模块,在网页上定位元素,获取数据re
模块当然也可以做到但是过于繁琐。
XPath
是一门在 XML 文档中查找信息的语言,用来在网页XML
文档中对元素和属性进行遍历,语法简单方便。
安装及了解更多:
Python爬虫利器三之Xpath语法与lxml库的用法
json与jsonpath
json
(JavaScript Object Notation)是一种轻量级的数据交换格式,具有数据格式简单,读写方便易懂等优点,相对于XML
来说,更加的轻量级,更方便解析,因此许多开发者都遵循json格式来进行数据的传输和交换。比如我们后面获取到的cookie和利用知乎API获取的回答信息都是json格式。
jsonpath
之于json
便如xptah
之于XML
,是专门用来解析json数据格式的模块,语法简洁比直接调用re
模块正则解析方便。
安装及了解更多:
JSON入门教程
json解析神器 jsonpath的使用
正如前言,模拟登陆知乎,有两种思路:
request
硬核破解:
知乎对Form Date数据进行了加密,要抓包分析同时对JavaScript有一定了解才能尝试分析出来。
可参阅:模拟登陆知乎
selenium
模拟登陆:
模拟真实打开浏览器登陆,拿到cookies,再用request爬取数据,难度较低,可操作性强。
这里我们采用第二种方式。
模拟登陆有多种方式,使用知乎登陆界面提供的QQ号登陆可以避免验证码,进而获取cookies。另外一种便是使用手机号登陆,需要验证码,将在1.2 详细讲述。
引入模块
from selenium import webdriver
from base64 import b64decode # 解码验证码b64编码,QQ登陆不用
import time # 用于暂停,防止被检测
import json # 保存json格式cookies,便于读取
import os # 主要用于创建文件夹等操作
打开浏览器
# 1.打开浏览器
browser = webdriver.Chrome()
browser.get('http://www.zhihu.com')
执行这段代码,便会看到程序自动打开Chrome浏览器,进入到知乎登陆界面。
找到QQ登陆按钮
# 2.找到QQ登陆按钮
# 先找到登陆按钮
bt_opt_login = browser.find_element_by_xpath('//div[@class="SignContainer-switch"]/span')
bt_opt_login .click()
# 再选择社交账号方式登陆
bt_opt_social = browser.find_element_by_xpath('//span[@class="Login-socialLogin"]/button')
bt_opt_social.click()
time.sleep(1) # 等等QQ登陆图标加载一下
# 最后点击QQ图标登陆
bt_opt_QQ = browser.find_element_by_xpath('//span[@class="Login-socialButtonGroup"]/button[3]')
bt_opt_QQ.click()
time.sleep(1) # 等待下加载完毕
注意,最后一步选择QQ图标登陆按钮时,大家可以看到,其在一对
标签所中:
如果大家直接xpath定位到g标签中:
//svg[@class="Icon Login-socialIcon Icon--qq"]/g
是不能定位成功的,定位svg元素要用xpath的name()函数,且自svg以下都要用:*[name()='svg element']
这种形式
//span[@class="Login-socialButtonGroup"]/button[3]/*[name()='svg']/*[name()='g']
也可以像上面,更简洁的直接定位到button[3]
按钮标签即可(第三个是QQ登陆按钮)。
切换到内置QQ登陆窗口登陆
点击QQ图标选择登陆后,便会弹出一个内嵌QQ登陆子网页。自然而然,我们要切换窗口:
# 3.操作刚打开的QQ登陆界面
# 切换到qq登陆界面句柄
allhandles = browser.window_handles
zhihuHandle = browser.current_window_handle
qqHandle = allhandles[1]
# qq登陆内嵌页面要切换表单
browser.switch_to.frame("ptlogin_iframe")
browser.window_handles
获取当前所有窗口句柄,第一个是知乎窗口,第二个自然是QQ登陆窗口。但是要提醒大家的是,QQ登陆是内嵌QQ登陆子网页,还需要切换表单frame,切换表单需要知道表单名,那么问题来了,如何找到当前QQ登陆子网页表单名?
F12>>分析网页元素,ctrl+shift+f 打开搜索框,输入frame
搜索,可以找到frame_name = ptlogin_iframe
,复制进行切换表单。
接下来,就是模拟输入账号密码点击登陆了,距离成功登陆只差一点点啦!接下来的代码也清晰易懂,主要就是定位元素,这里xpath
定位不太方便,直接查找id会更方便点。
# 选择输入密码登陆
bt_opt_inputAP = browser.find_element_by_xpath('//div[@id="bottom_qlogin"]')
bt_opt_inputAP.click()
# 开始模拟输入账号密码登陆
text_qq_account = browser.find_element_by_id("u")
text_qq_password = browser.find_element_by_id("p")
bt_qq_login = browser.find_element_by_id("login_button")
text_qq_account.send_keys("380141***") # 输入你的QQ账号
text_qq_password.send_keys("riguangyu******") # 输入你的QQ密码
bt_qq_login.click()
time.sleep(3)
最后大家不要忘了,切回知乎主窗口,表单不用切换。
# 切回知乎窗口,表单不用
browser.switch_to.window(zhihuHandle)
保存cookie
终于进入到知乎首页了,距离爬取好看的姑娘美照,啊不对更进一步学习更近了,哈哈~大家不要忘了我们辛苦模拟登陆就是为了拿到cookie,迫不及待来看看怎么保存cookie吧。
zhihu_cookies = browser.get_cookies()
hh,获取cookie还是还简单的,返回的zhihu_cookies
是一个字典类型。但是现在问题来了,如果我们直接将它写入txt文档,读取的时候是string类型,不再是字典,这样就很不方便读取里面数据了,总不然正则分析吧?
这个时候json
就闪亮登场了,我们用json.dumps
将cookie转为json格式写入txt,读取的时候再用json.load
方法读取,返回的就又是字典类型了。进一步了解,参照前: JSON入门教程
4.selenium保存cookie保存
zhihu_cookies = browser.get_cookies()
json_cookies = json.dumps(zhihu_cookies)
with open("C:\\Users\\86151\\Desktop\\json_cookies.txt", "w") as f:
f.write(json_cookies)
嗷嗷,就是一个列表嘛,里面每一项又是字典。记住这个形式,方便后面我们理解读取cookie。
前面虽然已经详细记录QQ模拟过程,但是我还是想记录下手机号登陆过程,因为这种登陆方式,必不可免的遇到处理验证码。如何处理验证码是学爬虫绕不过的坎,要撞的南墙。这里我将重点记录处理知乎验证的过程。如果迫不及待想看美羊羊洗澡,哦不小姐姐美照的同学可以略过这节。
基本操作
前面登陆过程和QQ登陆大同小异,这里直接给出代码供大家参考。
from selenium import webdriver
from base64 import b64decode # 解码验证码b64编码,QQ登陆不用
import time # 用于暂停,防止被检测
import json # 保存json格式cookies,便于读取
import os # 主要用于创建文件夹等操作
count = 0
while 1:
# 1.打开浏览器
# browser = webdriver.Chrome(chrome_options=chromeOptions)
browser = webdriver.Chrome()
browser.get('http://www.zhihu.com')
# 2.输入账号密码
# 1.点击登陆
bt_opt_login = browser.find_element_by_xpath('//div[@class="SignContainer-switch"]/span')
bt_opt_login .click()
time.sleep(1)
# 2.输入账号密码
# elem_account = browser.find_element_by_name("username")
# elem_pwd = browser.find_element_by_name("password")
text_account = browser.find_element_by_xpath('//input[@name="username"]')
text__pwd = browser.find_element_by_xpath('//input[@name="password"]')
text_account.send_keys("1517948****")
text__pwd.send_keys("riguangyu******")
# 3.模拟点击登陆
bt_login = browser.find_element_by_xpath('//button[@type="submit"]')
bt_login.click()
我们输入完手机号&密码点击登陆,本小节重点验证码boss便出现了,欲知我如何和验证码斗智斗勇大战三百回合且听下步分解。
处理验证码
知乎的验证码有两种,一种是还算人性化英文验证码:
一种便是毫无人性的中文验证码,要求我们点击图中倒立的中文字符:
中文验证码是比较难以处理的,我对它的处理方式就是:不处理~hh,简单来说,判断出现中文验证码就刷新界面,直至出现英文验证码开始输入验证码登陆。
那么问题又来了(废宅就是问题多hh),如何判断出现中文字符?首先,直接定位中文验证码元素,如何定位不成功报错,说明出现的是英文验证码。捕获异常进行处理英文验证码即可。
# 4.处理验证码登陆
# 4.1 获取英文验证码图片
time.sleep(1) # 等待一会儿验证码图片还没加载
# noinspection PyBroadException
try:
img_captcha = browser.find_element_by_class_name("Captcha-chineseImg") # 定位到图片元素| "Captcha-englishImg"
count += 1
print("中文字符暂时不能处理,第{0}次重试...\n".format(count))
browser.close()
time.sleep(1)
continue
except Exception as e:
img_captcha = browser.find_element_by_class_name("Captcha-englishImg")
img64_src = img_captcha.get_attribute("src") # 获取验证码b64编码
img64_src = img64_src.replace("data:image/jpg;base64,", "") # 删除前面标识
img64_src = img64_src.replace("%0A", "\n") # get_attribute会把\n替换成%OA,要替换回来
img_date = b64decode(img64_src)
大家可能会对验证码b64编码处理,这段代码有所疑问。
验证码是服务器自动生成的,不是给URL地址,而是一串b64编码字符,我们对它进行解码处理。可以看到下面这张图片,验证码b64编码见下:
特别注意get_attribute
这个方法会把\n替换成%OA,要替换回来
处理好验证码,我们可以把它保存在本地,然后打开,这样我们只要手工输入验证码就可以登录了。
# 4.2 保存图片
img_path = captcha_savePath + "\\captcha.png"
with open(img_path, "wb") as f: # 将验证码图片以二进制流写入保存
f.write(img_date)
# 4.3 打开图片
os.system(img_path)
captcha = input("已捕捉到英文验证码,请在打开的图片识别输入:")
time.sleep(2)
# 4.4 输入验证码登陆
elem_captcha_input = browser.find_element_by_xpath('//input[@name="captcha"]')
elem_captcha_input.send_keys(captcha)
# 4.5 登陆
bt_login1 = browser.find_element_by_xpath('//button[@type="submit"]')
bt_login1.click()
time.sleep(2)
验证码处理完毕便可以登录到知乎首页了,同1.1接下来保存cookie即可。
保存cookie
# 5.保存cookie
zhihu_cookies = browser.get_cookies()
json_cookies = json.dumps(zhihu_cookies)
with open("C:\\Users\\86151\\Desktop\\json_cookies.txt", "w") as f:
f.write(json_cookies)
拿到cookie后我们又要掏出我们的老伙计------requests
来爬取数据了。只要在requests请求时带上cookie参数,我们便可以相当于输入账号密码验证过身份直接登陆知乎了。
我们表面随便(预谋已久)拿知乎某著名相亲贴爬取下面回答姑娘的照片来试试手:你的择偶标准是怎样的
我们可以看到,知乎回答只有往下滑动才能加载出更多。而知乎URL一直没有变化,想直接简单观察构造URL是行不通了。
难道就这么放弃吗?我们爬虫,哦不,程序员绝不轻易认输!F12 分析网页元素,点击XHR
窥屏网站请求(XHR
类型即通过XMLHttpRequest
方法发送的请求,知乎要请求加载回答)。然后,我们开始滑动,往下加载回答,看看都有什么请求。
这个answer开头请求显然是非常可疑的,点进去窥视一下,发现有一大串的URL,复制过来我们把它粘贴过来打开浏览器访问(这里复制到firefox打开会自动转成json格式便于查看):
果不其然,这里就是请求的回答信息,服务器返回json格式。后来查阅了一下,没想到是知乎开放的API,我常威是靠某乎施舍…各位看官老爷,咋这就赶紧麻溜开始吧。上上张图片已经分析出下面这一大串URL规律:
limt
: 限制一次请求回答数,经过测试可以改为20,即一次请求20条回答。
offset
:偏移量,前面已有回答数。其余无变化。
明白了知乎是怎么请求了,接下来只要构造request
请求,会jsonpath
对知乎API返回的json数据进行处理,就可以愉快的爬下我们想要的数据了(你明白的)。
读取cookie构造request请求
正如前cookie所说的格式,是一个列表,每一项是字典。每一个字典里有很多键值对,我们只需每个字典都有的键name
&value
对应的值(其余的键值不用,这两个就够了),构造成一个新的 name值:value值
对应的新cookie字典。
# 5.读取cookies
cookies_dic = {}
with open("C:\\Users\\86151\\Desktop\\json_cookies.txt", "r") as f:
cookies = json.load(f)
# 在保存的cookies文档中,一个列表,每一项都是字典,字典又自然有多个键值对。只有每一个字典键值name,value对应的数据需要记住
for cookie in cookies:
cookies_dic[cookie['name']] = cookie['value']
然后再传入headers伪装浏览器,循环构造URL请求进行请求即可。
# 6.分析知乎帖子,正则匹配获取每篇答案的作者/赞同数/图片等信息
desktop_path = "C:\\Users\\86151\\Desktop"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}
answer_url = "https://www.zhihu.com/api/v4/questions/275359100/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=20&offset={0}&platform=desktop&sort_by=default"
# 爬十次,每次爬20篇回答,共200篇
for i in range(10):
dest_url = answer_url.format(i*20)
response = requests.get(dest_url, headers=headers, cookies=cookies_dic)
接下来,我们便开始用jsonpath
解析获取的数据
jsonpath解析数据
首先当然是用json.load加载读取到的数据,接着便是简单运用jsonpath对json数据进行解析:
# 爬取的是json格式,要读取分析用json.loads载入
json_date = json.loads(response.text)
# 保存这20篇回答:作者 & 回答内容
authors = jsonpath.jsonpath(json_date, '$..author.name')
contents = jsonpath.jsonpath(json_date, '$..content')
那么问题还是他喵又来了,回答里包含照片的URL地址信息,如何获得呢?jsonpath 和xpath肯定是不行的,什么你已经想到了?没错就是正则表达式(主要还是我睿智分析)!
令人窒息的是,同一张照片URL既可能出现在
# 循环在指定root_path创建以作者名命名的文件夹,里面放有相应回答照片
for j in range(20): # 下载20页,每页20篇回答
# 创建以作者名命名的文件夹
author_path = desktop_path+"\\知乎照片\\"+authors[j]
if not os.path.exists(author_path):
os.makedirs(author_path)
# 用re正则解析对应的回答内容里面的图片
img_pattern = re.compile('data-original="(.*?)"')
img_urls = re.findall(img_pattern, contents[j]) # 相邻两个重复
new_img_urls = []
index = 0
# 去除url相邻重复
for item in img_urls:
if index % 2 == 0:
new_img_urls.append(item)
index += 1
然后便是保存照片:
# 判断是否有图片
if len(new_img_urls) == 0:
print("无照片")
continue
# 下载图片
count = 0
for url in new_img_urls:
img_path = author_path + "\\" + str(count) + ".jpg"
response_img = requests.get(url)
with open(img_path, "wb") as f:
f.write(response_img.content) # 注意要用response_img.content
count += 1
print("第{0}篇回答照片下载完毕".format(i*20+j+1))
time.sleep(5)
要注意的是,要用response_img.content
(二进制格式)写入照片 而不是response_img.text
(字符串)。
到这里,我们等待下载完毕便可以啦!接下来,就是激动人心查看战果时间~
这里我们发现了一点小瑕疵,有些图片下载失败,经过排查URL请求是正确的,单独下载也能成功,某些不可描述因素?后续如果解决,会进行更新~
至此,知乎爬虫便基本制作成功了,接下来就是进行面对对象的重构,以及此次项目总结一些善后工作了。
from selenium import webdriver
from base64 import b64decode
import requests
import re
import time
import json
import jsonpath
import os
class zhihuSpider:
def __init__(self):
# 初始化headers、登陆界面url、
self.loginURL = "http://www.zhihu.com"
self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}
def zhihu_qq_login(self, account, password):
"""
:param account: 账号
:param password: 密码
:return: 尝试qq登陆,返回只含有键值name,value对应字典cookie
"""
# 1.打开浏览器
browser = webdriver.Chrome()
browser.get(self.loginURL)
# 2.查找登陆元素
# 点击登陆
# 因为'登陆'在一对登陆标签中,但是没有元素属性不好精确定位,采用XPATH语法
bt_opt_login = browser.find_element_by_xpath('//div[@class="SignContainer-switch"]/span')
bt_opt_login.click()
# 选择QQ号登陆
bt_opt_social = browser.find_element_by_xpath('//span[@class="Login-socialLogin"]/button')
bt_opt_social.click()
time.sleep(1) # 等等QQ登陆图标加载一下
bt_opt_QQ = browser.find_element_by_xpath('//span[@class="Login-socialButtonGroup"]/button[3]')
bt_opt_QQ.click()
# 3.操作刚打开的QQ登陆窗口
time.sleep(1) # 等待下加载完毕
# 切换到qq登陆窗口
allhandles = browser.window_handles
zhihuHandle = browser.current_window_handle
qqHandle = allhandles[1]
browser.switch_to.window(qqHandle)
# 同时qq登陆内嵌页面要切换表单:ctrl+shift+f搜索:frame,找到frame name = ptlogin_iframe
browser.switch_to.frame("ptlogin_iframe")
# 选择输入密码登陆
bt_opt_inputAP = browser.find_element_by_xpath('//div[@id="bottom_qlogin"]')
bt_opt_inputAP.click()
# 开始模拟输入账号密码登陆
text_qq_account = browser.find_element_by_id("u")
text_qq_password = browser.find_element_by_id("p")
bt_qq_login = browser.find_element_by_id("login_button")
text_qq_account.send_keys(account)
text_qq_password.send_keys(password)
bt_qq_login.click()
time.sleep(3)
# 切回知乎窗口,表单不用
browser.switch_to.window(zhihuHandle)
# 4.返回含指定键值的cookie字典
# zhihucookie是列表含有多项,每项都是字典类型;这里不用txt保存,故无需解析成json数据
zhihu_cookies = browser.get_cookies()
cookies_dic = {} # 只保存键值name,value对应的数据
for cookie in zhihu_cookies:
cookies_dic[cookie['name']] = cookie['value']
browser.close()
return cookies_dic
def zhihu_phoneNum_login(self, account, password, captcha_savePath):
"""
循环模拟登陆知乎,直至出现的是英文验证码,输入验证码登陆
:param account: 账号
:param password: 密码
:return: 尝试手机号登陆,返回只含有键值name,value对应字典cookie
"""
count = 0
while 1:
# 1.打开浏览器
browser = webdriver.Chrome()
browser.get('http://www.zhihu.com')
# 2.查找登陆元素
# 1.点击登陆
bt_opt_login = browser.find_element_by_xpath('//div[@class="SignContainer-switch"]/span')
bt_opt_login.click()
# 2.输入账号密码
time.sleep(1)
# elem_account = browser.find_element_by_name("username")
# elem_pwd = browser.find_element_by_name("password")
text_account = browser.find_element_by_xpath('//input[@name="username"]')
text__pwd = browser.find_element_by_xpath('//input[@name="password"]')
text_account.send_keys(account)
text__pwd.send_keys(password)
# 3.模拟点击登陆
bt_login = browser.find_element_by_xpath('//button[@type="submit"]')
bt_login.click()
# 4.处理验证码登陆
# 1.获取验证码图片
time.sleep(1) # 等待一会儿验证码图片还没加载
# noinspection PyBroadException
try:
# 定位到中文验证码,刷新浏览器重新登陆。
img_captcha = browser.find_element_by_class_name("Captcha-chineseImg")
print("中文字符暂时不能处理,第{0}次重试...\n".format(count + 1))
browser.refresh()
time.sleep(1)
continue
except Exception as e:
# 定位中文验证码出错,则说明定位到英文验证码,开始识别人工输入
# 验证码是服务器生成b64编码,直接进行解码写入保存即可,不用下载
# 定位到验证码元素
img_captcha = browser.find_element_by_class_name("Captcha-englishImg")
# 获取元素内的验证码b64编码
img64_src = img_captcha.get_attribute("src")
# 对编码进行一些处理可解码
img64_src = img64_src.replace("data:image/jpg;base64,", "") # 删除前面标识
img64_src = img64_src.replace("%0A", "\n") # get_attribute会把\n替换成%OA,要替换回来
img_date = b64decode(img64_src)
# 2.保存图片
img_path = captcha_savePath + "\\captcha.png"
with open(img_path, "wb") as f: # 将验证码图片以二进制流写入保存
f.write(img_date)
# 3.打开图片
os.system(img_path)
captcha = input("已捕捉到英文验证码,请在打开的图片识别输入:")
time.sleep(2)
# 4. 输入验证码登陆
elem_captcha_input = browser.find_element_by_xpath('//input[@name="captcha"]')
elem_captcha_input.send_keys(captcha)
# 5.登陆
bt_login1 = browser.find_element_by_xpath('//button[@type="submit"]')
bt_login1.click()
time.sleep(2)
# 5.已经成功登陆,返回含指定键值的cookie字典
# zhihucookie是列表含有多项,每项都是字典类型;这里不用txt保存,故无需解析成json数据
print("成功登陆!即将开始下载...")
zhihu_cookies = browser.get_cookies()
cookies_dic = {} # 只保存键值name,value对应的数据
for cookie in zhihu_cookies:
cookies_dic[cookie['name']] = cookie['value']
browser.close()
return cookies_dic
def download(self, cookies_dic, answer_url, img_savepath, pages, limit=20):
"""
下载知乎指定任意问题下图片
:param cookies_dic: 知乎cookie
:param answer_url: 知乎问题url
:param img_savepath: 知乎问题下图片保存路径
:param pages: 下载多少页
:param limit: 一页默认限定20篇回答
:return:
"""
# 爬十页,每页爬20篇回答,共200篇
for p in range(pages):
dest_url = answer_url.format(limit, p * limit)
response = requests.get(dest_url, headers=self.headers, cookies=cookies_dic)
# 爬取的是json格式,要读取分析用json.loads载入
json_date = json.loads(response.text)
# 保存这20篇回答:作者、答案中图片
authors = jsonpath.jsonpath(json_date, '$..author.name')
contents = jsonpath.jsonpath(json_date, '$..content')
# 循环在指定root_path创建以作者名命名的文件夹,里面放有相应回答照片
for l in range(limit):
# 创建以作者名命名的文件夹
author_path = img_savepath + "\\知乎照片1\\" + authors[l]
if not os.path.exists(author_path):
os.makedirs(author_path)
# 用re正则解析对应的回答内容里面的图片
img_pattern = re.compile('data-original="(.*?)"')
img_urls = re.findall(img_pattern, contents[l]) # 相邻两个重复
new_img_urls = []
index = 0
# url相邻重复,去除
for url in img_urls:
if index % 2 == 0:
new_img_urls.append(url)
index += 1
# 判断是否有图片
if len(new_img_urls) == 0:
print("无照片")
continue
# 下载图片
count = 0
for url in new_img_urls:
img_path = author_path + "\\" + str(count) + ".jpg"
response_img = requests.get(url)
with open(img_path, "wb") as f:
f.write(response_img.content)
count += 1
print("第{0}篇回答照片下载完毕".format(p * limit + l + 1))
time.sleep(5) # 等待5s,开始下载下一页
print("下载完毕!")
if __name__ == '__main__':
answer_url = "https://www.zhihu.com/api/v4/questions/275359100/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit={0}&offset={1}&platform=desktop&sort_by=default"
desktop_path = "C:\\Users\\86151\\Desktop"
spider = zhihuSpider()
# cookies_dir = spider.zhihu_qq_login("380141****", "riguangyu*****")
cookies_dir = spider.zhihu_phoneNum_login("1517948****", "riguangyu***", desktop_path)
spider.download(cookies_dir, answer_url, desktop_path, 10)
呼呼,终于完成了!最开始接触爬虫,便想着爬取知乎小姐姐照片,成功的那一刻还是挺有成就感的。下一篇博文便是记录破解bilibili滑块验证码了,你滑任你滑,我爬我的虫~
下次再见啦!对了,俺也不是要求太多,这么详细的知乎爬虫记录,各位看官老爷不点个关注/喜欢嘛?谢谢您的鼓励~