? ?
?? 刚学爬虫时,看到一篇文章硬核破解知乎登陆,心潮澎湃,真男人!符合我的胃口!哼哧哼哧的立刻安排!
??(半个小时过后)
??似乎我是弱智?很多看不懂?(百度乱搜中…)恩还有种简单的?selenium
+xpath
模拟登陆?简单但效率低?难道要靠用这种低效率方式来爬取数据,这是向网站妥协!不,我常威就算没技术也绝对不要这样委屈求全!(十分钟过后)挨,怎么他喵这么香?
?? 经过一番曲折的故事(中间花了半个月拿了几个小项目练练手),终于进入激动人心的实战,马上就可以 爬取知乎姑娘的美照 学到新知识了!本文行文结构如下:
? ?1. 做好准备了吗
? ?2. selenium
+xpath
模拟登陆知乎获取cookies
? ?3. request
+re
+json
+jsonpath
爬取知乎指定问题下所有回答数据(照片)
? ?4. 进行面对对象重新构造
? ?5. 总结
?
0、 做好准备了吗 ?
- 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)
? ? 让我们看看txt里都写入了啥:
![爬虫实战3(模拟登陆知乎并爬取任意帖子数据)](https://img.it610.com/image/info8/a284ca6d9dad411cb981b689c623726d.jpg)
文章图片
? ?嗷嗷,就是一个列表嘛,里面每一项又是字典。记住这个形式,方便后面我们理解读取cookie。
?
1.2 开始模拟登陆2:手机号模拟登陆
?
? ?前面虽然已经详细记录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 = https://www.it610.com/article/img_captcha.get_attribute("src")# 获取验证码b64编码 img64_src = https://www.it610.com/article/img64_src.replace("data:image/jpg; base64,", "")# 删除前面标识 img64_src = https://www.it610.com/article/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即可。
?
- 验证码是服务器自动生成的,不是给URL地址,而是一串b64编码字符,我们对它进行解码处理。可以看到下面这张图片,验证码b64编码见下:
- 保存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既可能出现在
文章图片
文章图片
? ? 这里我们发现了一点小瑕疵,有些图片下载失败,经过排查URL请求是正确的,单独下载也能成功,某些不可描述因素?后续如果解决,会进行更新~
? ?至此,知乎爬虫便基本制作成功了,接下来就是进行面对对象的重构,以及此次项目总结一些善后工作了。
三、面对对象重构 ?
from selenium import webdriver
from base64 import b64decode
import requests
import re
import time
import json
import jsonpath
import osclass 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_dicdef 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 = https://www.it610.com/article/img_captcha.get_attribute("src")
# 对编码进行一些处理可解码
img64_src = https://www.it610.com/article/img64_src.replace("data:image/jpg;
base64,", "")# 删除前面标识
img64_src = https://www.it610.com/article/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_dicdef 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滑块验证码了,你滑任你滑,我爬我的虫~
【爬虫实战3(模拟登陆知乎并爬取任意帖子数据)】? ?下次再见啦!对了,俺也不是要求太多,这么详细的知乎爬虫记录,各位看官老爷不点个关注/喜欢嘛?谢谢您的鼓励~
推荐阅读
- 爬虫|若想拿下爬虫大单,怎能不会逆向爬虫,价值过万的逆向爬虫教程限时分享
- python|尚硅谷python爬虫(二)-解析方法
- web挖洞|HACK学习黑帽子Python--漏洞检测脚本快速编写
- Pyecharts|Pyecharts 猎聘招聘数据可视化
- Python爬虫笔记|Python爬虫学习笔记_DAY_17_Python爬虫之使用cookie绕过登录的介绍【Python爬虫】
- Python爬虫笔记|Python爬虫学习笔记_DAY_19_Python爬虫之代理ip与代理池的使用介绍【Python爬虫】
- Python爬虫笔记|Python爬虫学习笔记_DAY_18_Python爬虫之handler处理器的使用【Python爬虫】
- python|用 Python 写一副春联&福字,把最好的祝福,送给重要的人
- 爬虫|淘宝商品数据爬取
- 爬虫学习历程小记