陈不诌知乎文章链接页面:https://www.zhihu.com/people/chen-bu-zou/posts/posts_by_votes
单击右键→进入审查元素→选择Network→选择ALL→刷新网页之后进入posts_by_votes→查看Preview【发现内容是存放在html页面中】
通过层层检索发现,标签为 ContentItem-title 的内容可以锁定文章标题,如下图框示
1.获取数据——用requests库;
2.解析数据——用BeautifulSoup库;
3.提取数据——用BeautifulSoup里的find_all(),翻页的话观察第一页,到最后一页的网址特征,写循环;
4.存储数据——用csv存储内容。
1.1获取数据:检查爬虫是否能够正常运转
import requests
from bs4 import BeautifulSoup
#引入request和bs
url='https://www.zhihu.com/people/chen-bu-zou/posts/posts_by_votes'
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
#使用headers是一种默认的习惯
res=requests.get(url,headers=headers)
#发起请求,将响应的结果赋值给变量res。
print(res.status_code)
#检查状态码
1.2对标题进行爬虫显示测试
import requests
from bs4 import BeautifulSoup
#引入request和bs
url='https://www.zhihu.com/people/chen-bu-zou/posts/posts_by_votes'
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
#使用headers是一种默认的习惯
res=requests.get(url,headers=headers)
#发起请求,将响应的结果赋值给变量res。
print(res.status_code)
#检查状态码
bstitle=BeautifulSoup(res.text,'html.parser')
#用bs进行解析
title=bstitle.findAll(class_='ContentItem-title')
#提取我们想要的标签和里面的内容
print(title)
#打印title
1.3对标题内容进行排查检查
使用 res.text 打印网页源代码进行排查检查
import requests
from bs4 import BeautifulSoup
#引入request和bs
url='https://www.zhihu.com/people/chen-bu-zou/posts/posts_by_votes'
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
#使用headers是一种默认的习惯
res=requests.get(url,headers=headers)
#发起请求,将响应的结果赋值给变量res。
print(res.status_code)
#检查状态码
print(res.text)
#打印网页源代码
翻看爬虫全文内容,发现知乎在html网页中,只放置了两个标题内容
1.4重新对网页进行分析【找出标题所应该在的位置】
1.5翻页(点击下一页)查看参数区别
第一页如图
第二页内容
综合两个数据来看,发现除了offset参数,其他都一样。offset代表起始值,limit表示加载的限制数,通过循环我们是可以爬到所有页数的内容了。
a.获取数据:拿请求里面的headers里面的request url,操作为response对象
b.解析数据:使用response.json()解析json数据
c.提取数据:根据列表和字典的相关知识,提取需要的文章标题、摘要和链接,拿完第一页之后、对比第一页和第二页的request url,发现区别,然后用循环写入
d.存储数据:使用csv存储数据
2.1获取数据:检查爬虫是否能够正常运转
找到标题数据所在的请求页面的Request URL,再用requests.get()获取
标题请求页url为:https://www.zhihu.com/api/v4/members/chen-bu-zou/articles?
用requests.get()获取数据,然后检查请求是否成功。
import requests
#引入requests
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
#封装headers
url='https://www.zhihu.com/api/v4/members/chen-bu-zou/articles?'
#写入网址
params={
'include':'data[*].comment_count,suggest_edit,is_normal,thumbnail_extra_info,thumbnail,can_comment,comment_permission,admin_closed_comment,content,voteup_count,created,updated,upvoted_followees,voting,review_info,is_labeled,label_info;data[*].author.badge[?(type=best_answerer)].topics',
'offset':'10',
'limit':'20',
'sort_by':'voteups',
}
#封装参数
res=requests.get(url,headers=headers,params=params)
#发送请求,并把响应内容赋值到变量res里面
print(res.status_code)
#确认请求成功
结果显示200,表示请求成功
2.2解析数据:解析json数据(提取标题信息)
从以上三张图可以得出以下结论:
最外层是一个很大的字典,里面有两大元素,data:和paging:,这两大元素又是键值对应的字典形式,data这个键所对应的值是一个列表,里面有10元素,每个元素又是字典形式。
所需要提取的内容title,在键为data的值里面,第0个元素的值里面,字典中。
2.2提取标题及内容:提取第1页的所有标题、文章链接、摘要内容
代码示例
import requests
#引入requests
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
#封装headers
url='https://www.zhihu.com/api/v4/members/chen-bu-zou/articles?'
#写入网址
params={
'include':'data[*].comment_count,suggest_edit,is_normal,thumbnail_extra_info,thumbnail,can_comment,comment_permission,admin_closed_comment,content,voteup_count,created,updated,upvoted_followees,voting,review_info,is_labeled,label_info;data[*].author.badge[?(type=best_answerer)].topics',
'offset':'10',
'limit':'20',
'sort_by':'voteups',
}
#封装参数
res=requests.get(url,headers=headers,params=params)
#发送请求,并把响应内容赋值到变量res里面
print(res.status_code)
#确认这个response对象状态正确
articles=res.json()
#用json()方法去解析response对象,并赋值到变量articles上面,此时的articles是一个
print(articles)
#打印这个json文件
data=articles['data']
#取出键为data的值。
for i in data:
print(i['title'])
print(i['url'])
print(i['excerpt'])
#遍历列表,拿到的是列表里的每一个元素,这些元素都是字典,再通过键把值取出来
2.3提取其他页面标题及内容(判断翻页信息)
在上一步已经分析过,第一页和第二页的请求的参数区别在于offset,由此可以写一个循环。
结束循环的方式:
1.第一页的is_end是显示false,最后一页的is_end是显示true,这个元素可以结束循环。
2.totals:26 为文章总数,通过这个数字也可以结束循环。
爬取代码示意
import requests
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
url='https://www.zhihu.com/api/v4/members/chen-bu-zou/articles?'
articlelist=[]
#建立一个空列表,以待写入数据
offset=0
#设置offset的起始值为0
while True:
params={
'include':'data[*].comment_count,suggest_edit,is_normal,thumbnail_extra_info,thumbnail,can_comment,comment_permission,admin_closed_comment,content,voteup_count,created,updated,upvoted_followees,voting,review_info,is_labeled,label_info;data[*].author.badge[?(type=best_answerer)].topics',
'offset':str(offset),
'limit':'20',
'sort_by':'voteups',
}
#封装参数
res=requests.get(url,headers=headers,params=params) #发送请求,并把响应内容赋值到变量res里面
articles=res.json()
# print(articles)
data=articles['data'] #定位数据
for i in data:
list1=[i['title'],i['url'],i['excerpt']] #把数据封装成列表
articlelist.append(list1)
offset=offset+20 #在while循环内部,offset的值每次增加20
#if offset>40: #方案一:如果offset大于40,即爬了两页,就停止
# break
if articles['paging']['is_end'] == True: #方案二:如果键is_end所对应的值是True,就结束while循环。
break
print(articlelist) #打印
2.4存储爬虫数据(csv存储数据)
代码示意
import requests
import csv #引用csv
csv_file=open('articles.csv','w',newline='',encoding='utf-8') #调用open()函数打开csv文件,传入参数:文件名“articles.csv”、写入模式“w”、newline=''。
writer = csv.writer(csv_file) #用csv.writer()函数创建一个writer对象
list2=['标题','链接','摘要'] #创建一个列表
writer.writerow(list2) #调用writer对象的writerow()方法,可以在csv文件里写入一行文字 “标题”和“链接”和"摘要"
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
url='https://www.zhihu.com/api/v4/members/chen-bu-zou/articles?'
offset=0 #设置offset的起始值为0
while True:
params={
'include':'data[*].comment_count,suggest_edit,is_normal,thumbnail_extra_info,thumbnail,can_comment,comment_permission,admin_closed_comment,content,voteup_count,created,updated,upvoted_followees,voting,review_info,is_labeled,label_info;data[*].author.badge[?(type=best_answerer)].topics',
'offset':str(offset),
'limit':'20',
'sort_by':'voteups',
}
#封装参数
res=requests.get(url,headers=headers,params=params) #发送请求,并把响应内容赋值到变量res里面
articles=res.json()
print(articles)
data=articles['data'] #定位数据
for i in data:
list1=[i['title'],i['url'],i['excerpt']] #把目标数据封装成一个列表
writer.writerow(list1)
#调用writerow()方法,把列表list1的内容写入
offset=offset+20 #在while循环内部,offset的值每次增加20
if offset > 40:
break
csv_file.close() #写入完成后,关闭文件就大功告成
print('okay')