PYTHON爬虫(2):利用requests库和re库批量爬取知乎关于电影中的答案

5 篇文章 1 订阅
1 篇文章 0 订阅

上篇文章通过一个实例简要说明了如何用requests库和re库批量爬取图片,本篇文章将用另外一个实例说明如何爬取知乎上的回答并进行整理。

(一):引入相关库

import re
import requests

(二):改写headers伪装浏览器

# 知乎有反爬虫,加入http headers伪装浏览器
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
    "Connection": "keep-alive",
    "Accept": "text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "zh-CN,zh;q=0.8"}

伪装头部是最基本的反反爬虫方法,如果不进行伪装,对方网站可以直接通过headers中的"User-Agent"信息判断出我是通过python的requests库对网页进行请求访问的。

(三):相关参数设置

question_id = 38485891
interval = 20
offset = 0
rank = 100
novels_count = dict()
p = re.compile(r'《.+?》') # 正则匹配被《》括起来的电影名

question_id很好理解:每个知乎问题都有一个独一无二的id用来区分
interver为间隔:这里设为20,意味着每次爬取某一个问题的20个回答
offset为偏移量,初始为0,意味着从第一个答案进行爬取
rank为打印数量,在后续打印排名时才会用到
novels_count初始设为一个空字典,用来存储所获取的电影信息
p为正则表达式,匹配被书名号括起来的电影名

(四):批量爬取答案

while True:
    print(f'答案数 {offset} 到 {offset + interval}')
    # 知乎获取回答分页API
    url = f'https://www.zhihu.com/api/v4/questions/{question_id}/answers?include=content&limit={interval}&offset={offset}&sort_by=default'
    html = requests.get(url, headers=headers)
    answers = html.json()['data']
    if len(answers) == 0:
        break
    for answer in answers:
        results = set(re.findall(p, answer['content'])) # 结果去重,过滤掉同一个回答里的多次提及导致的重复统计
        for novel_name in results:
            if novel_name in novels_count:
                novels_count[novel_name] += 1
            else:
                novels_count[novel_name] = 1
    offset += interval

这段代码有一些值得注意的地方:
(1)python的print字符串前面加f表示格式化字符串,加f后可以在字符串里面使用用花括号括起来的变量和表达式,对url的赋值同理。
(2)set() 函数创建一个无序不重复元素集,删去同一个答案中的重复电影名称

(五):对结果进行降序排序

# 把结果按提名次数从高到低排序
novels_rank_list = sorted(novels_count.items(), key=lambda x: x[1], reverse=True)
print(f'提名电影总数:{len(novels_rank_list)}')

(1)items() 方法的遍历:items() 方法把字典中每对 key 和 value 组成一个元组,并把这些元组放在列表中返回。
(2)lambda是一个隐函数,是固定写法,不要写成别的单词;x表示列表中的一个元素,在这里,表示一个元组,x只是临时起的一个名字,你可以使用任意的名字;x[0]表示元组里的第一个元素

(六):对降序排序后的结果进行打印

# 打印前50
for i, novel in enumerate(novels_rank_list):
    if i > rank - 1:
        break
    name = novel[0]
    num = novel[1]
    print(f'{i + 1}.{name}提名{num}次')

(1)enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

我将这个问题答案进行了整理并将整理后的内容写在了知乎这一问题下,现给出原文链接,有兴趣的朋友可以看一看~~
https://www.zhihu.com/question/38485891/answer/1017573264

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值