赞
踩
刚学爬虫时,看到一篇文章硬核破解知乎登陆,心潮澎湃,真男人!符合我的胃口!哼哧哼哧的立刻安排!
(半个小时过后)
似乎我是弱智?很多看不懂?(百度乱搜中…)恩还有种简单的?selenium
+xpath
模拟登陆?简单但效率低?难道要靠用这种低效率方式来爬取数据,这是向网站妥协!不,我常威就算没技术也绝对不要这样委屈求全!(十分钟过后)挨,怎么他喵这么香?
经过一番曲折的故事(中间花了半个月拿了几个小项目练练手),终于进入激动人心的实战,马上就可以 爬取知乎姑娘的美照 学到新知识了!本文行文结构如下:
1. 做好准备了吗
2. selenium
+xpath
模拟登陆知乎获取cookies
3. request
+re
+json
+jsonpath
爬取知乎指定问题下所有回答数据(照片)
4. 进行面对对象重新构造
5. 总结
selenium 安装配置教程
selenium
及相应环境驱动配置安装,请查看:
什么是selenium
不知道大家有没有用过按键精灵的API,用这套API我们就可以进行点击、输入等一系列模拟真实用户操作。selenium和其类似,只不过它可直接作用于浏览器,模拟打开、进行点击,输入等操作。用它可以很方便避开反爬机制,拿到我们要的界面源码进而获取数据,但是缺点速度太慢。
了解更多:
什么是xpath
前面我们介绍过正则表达式和相应re
模块,在网页上定位元素,获取数据re
模块当然也可以做到但是过于繁琐。
XPath
是一门在 XML 文档中查找信息的语言,用来在网页XML
文档中对元素和属性进行遍历,语法简单方便。
安装及了解更多:
json与jsonpath
json
(JavaScript Object Notation)是一种轻量级的数据交换格式,具有数据格式简单,读写方便易懂等优点,相对于XML
来说,更加的轻量级,更方便解析,因此许多开发者都遵循json格式来进行数据的传输和交换。比如我们后面获取到的cookie和利用知乎API获取的回答信息都是json格式。
jsonpath
之于json
便如xptah
之于XML
,是专门用来解析json数据格式的模块,语法简洁比直接调用re
模块正则解析方便。
安装及了解更多:
正如前言,模拟登陆知乎,有两种思路:
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图标登陆按钮时,大家可以看到,其在一对<g></g>
标签所中:
如果大家直接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里都写入了啥:
嗷嗷,就是一个列表嘛,里面每一项又是字典。记住这个形式,方便后面我们理解读取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既可能出现在<img src…标签中,也可能出现在data-original= …中,那么到底正则匹配哪个?经过一番尝试,如果匹配<img src…标签图片URL,会出现很多无关图片;匹配data-original= …中图片URL,不会出现无关照片,但是相邻两张图片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.查找登陆元素 # 点击登陆 # 因为'登陆'在一对<span>登陆</span>标签中,但是没有元素属性不好精确定位,采用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滑块验证码了,你滑任你滑,我爬我的虫~
下次再见啦!对了,俺也不是要求太多,这么详细的知乎爬虫记录,各位看官老爷不点个关注/喜欢嘛?谢谢您的鼓励~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。