python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】

爬取知乎 “陈不诌”的文章“标题”、“摘要”、“链接”,并存储到本地文件

陈不诌知乎文章链接页面:https://www.zhihu.com/people/chen-bu-zou/posts/posts_by_votes

操作步骤梳理

第一步:查看内容存放位置

python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第1张图片
单击右键→进入审查元素→选择Network→选择ALL→刷新网页之后进入posts_by_votes→查看Preview【发现内容是存放在html页面中】

第二步:查看网页源代码(定位文章标题)

python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第2张图片
通过层层检索发现,标签为 ContentItem-title 的内容可以锁定文章标题,如下图框示
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第3张图片

梳理整体爬虫思路

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)
#检查状态码

在这里插入图片描述
✔结果显示 200,表示可正常爬虫

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)
#打印网页源代码

python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第4张图片
翻看爬虫全文内容,发现知乎在html网页中,只放置了两个标题内容
1.4重新对网页进行分析【找出标题所应该在的位置】
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第5张图片
1.5翻页(点击下一页)查看参数区别
第一页如图
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第6张图片
第二页内容
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第7张图片
综合两个数据来看,发现除了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数据(提取标题信息)
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第8张图片
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第9张图片
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第10张图片
从以上三张图可以得出以下结论:
最外层是一个很大的字典,里面有两大元素,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提取其他页面标题及内容(判断翻页信息)
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第11张图片
在上一步已经分析过,第一页和第二页的请求的参数区别在于offset,由此可以写一个循环。
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第12张图片
python笔记 爬虫精进·第7课 【知乎内容爬虫解析,爬取知乎文章题目、链接、摘要】_第13张图片
结束循环的方式:
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')

你可能感兴趣的:(python学习笔记)