Python实战爬虫技巧:使用Requests库轻松爬取知乎热榜内容

引言

知乎作为中国最大的问答社区之一,其热榜内容反映了当前互联网用户关注的热点话题。通过爬取知乎热榜,我们可以获取实时热点数据,用于舆情分析、趋势预测或内容创作。本文将详细介绍如何使用 Python 的 requests 库结合 BeautifulSoupJSON 解析技术,从知乎热榜页面提取热门话题数据,并涵盖反爬虫策略、数据存储及可视化等内容。文章将从基础环境搭建到进阶技巧全面讲解,适合初学者和有一定爬虫经验的开发者。

第一部分:环境准备与依赖安装

1. 安装必要的 Python 库

知乎热榜页面的内容可以通过 HTML 或 API 接口获取,因此我们需要安装以下库:

  • requests: 用于发送 HTTP 请求。
  • BeautifulSoup: 用于解析 HTML 内容(静态页面)。
  • pandas: 用于数据存储和处理。
  • json: 用于解析 API 返回的 JSON 数据。
  • timerandom: 用于模拟用户行为,规避反爬虫机制。
  • pip install requests beautifulsoup4 pandas
    

    第二部分:爬取知乎热榜页面(静态HTML解析)

    2.1 分析知乎热榜页面结构

    知乎热榜页面的 URL 为 https://www.zhihu.com/hot,页面包含 50 条热门话题。通过浏览器开发者工具(F12)查看页面结构,发现热榜内容位于 <section class="HotItem-content"> 标签中,每个话题包含标题、链接和热度值。

    2.2 发送请求并获取页面内容

    由于知乎需要登录才能访问热榜页面,因此需要在请求头中携带有效的 Cookie。以下是代码示例:

    import requests
    
    # 目标URL
    url = "https://www.zhihu.com/hot"
    
    # 请求头(需替换 Cookie 值)
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
        "Cookie": "你的知乎登录Cookie值"  # 替换为你的实际Cookie
    }
    
    # 发送GET请求
    response = requests.get(url, headers=headers)
    
    # 检查响应状态码
    if response.status_code == 200:
        html_content = response.text
        print("页面获取成功!")
    else:
        print(f"请求失败,状态码:{response.status_code}")
    

    注释

  • Cookie 获取方法:登录知乎后,打开开发者工具,进入 “Network” 选项卡,找到任意请求的 Headers,复制 Cookie 字段的值。
  • User-Agent:模拟浏览器访问,避免被服务器识别为爬虫。
  • 2.3 解析 HTML 并提取热榜数据

    使用 BeautifulSoup 解析 HTML 内容,提取标题、链接和热度值:

    from bs4 import BeautifulSoup
    
    # 解析HTML
    soup = BeautifulSoup(html_content, 'lxml')
    
    # 定位热榜列表
    hot_items = soup.select('.HotList-list section')
    
    # 存储数据的列表
    data = []
    
    # 遍历每个热榜条目
    for index, item in enumerate(hot_items, start=1):
        title = item.select_one('.HotItem-title').text.strip()  # 标题
        link = item.select_one('a')['href']  # 链接
        hot_value = item.select_one('.HotItem-meta').text.strip()  # 热度值
        
        data.append({
            "排名": index,
            "标题": title,
            "链接": f"https://www.zhihu.com{link}",
            "热度值": hot_value
        })
    
    # 打印前5条数据
    for entry in data[:5]:
        print(entry)
    

    注释

  • CSS选择器.HotList-list section 用于定位热榜容器,.HotItem-title.HotItem-meta 是标题和热度值的类名。
  • 链接拼接:知乎链接为相对路径,需手动拼接完整 URL。
  • 第三部分:通过知乎API接口获取热榜数据

    3.1 分析API接口

    知乎热榜数据也可以通过其 API 接口获取,返回格式为 JSON,无需解析 HTML。接口地址为:

    https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=50&desktop=true
    

    3.2 发送请求并解析JSON数据

    import requests
    import json
    
    # API接口URL
    api_url = "https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=50&desktop=true"
    
    # 请求头(需替换 Cookie 值)
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
        "Cookie": "你的知乎登录Cookie值",
        "Referer": "https://www.zhihu.com/hot"
    }
    
    # 发送GET请求
    response = requests.get(api_url, headers=headers)
    
    # 检查响应状态码
    if response.status_code == 200:
        json_data = response.json()
        data = []
        
        # 遍历JSON数据
        for idx, item in enumerate(json_data['data'], start=1):
            title = item['target']['title_area']['text']  # 标题
            link = item['target']['content']['href']  # 链接
            hot_value = item['hot_score']  # 热度值
            desc = item['target']['excerpt_area']['text']  # 描述
            
            data.append({
                "排名": idx,
                "标题": title,
                "链接": f"https://www.zhihu.com{link}",
                "热度值": hot_value,
                "描述": desc
            })
        
        # 打印前5条数据
        for entry in data[:5]:
            print(entry)
    else:
        print(f"请求失败,状态码:{response.status_code}")
    

    注释

  • JSON结构json_data['data'] 包含所有热榜条目,每个条目的标题、链接和描述位于 target 字段下。
  • 字段提取:通过 item['target']['title_area']['text'] 可提取标题,类似方式提取其他字段。
  • 第四部分:数据存储与可视化

    4.1 存储为CSV文件

    使用 pandas 将数据保存为 CSV 文件,便于后续分析:

    import pandas as pd
    
    # 创建DataFrame
    df = pd.DataFrame(data)
    
    # 保存为CSV文件
    df.to_csv("zhihu_hot_list.csv", index=False, encoding="utf-8-sig")
    print("数据已保存为 zhihu_hot_list.csv")
    

    4.2 数据可视化

    使用 matplotlib 绘制热榜热度值分布图:

    import matplotlib.pyplot as plt
    
    # 提取热度值
    hot_values = [int(item["热度值"]) for item in data]
    
    # 绘制柱状图
    plt.figure(figsize=(12, 6))
    plt.bar(range(1, 51), hot_values, color='skyblue')
    plt.xlabel("排名")
    plt.ylabel("热度值")
    plt.title("知乎热榜热度值分布")
    plt.xticks(range(1, 51, 5))
    plt.grid(axis='y', linestyle='--', alpha=0.7)
    plt.show()
    

    第五部分:反爬虫策略与优化

    5.1 设置请求间隔

    频繁请求可能触发反爬虫机制,建议在每次请求后添加随机延迟:

    import time
    import random
    
    # 在请求前添加随机延迟(1~3秒)
    time.sleep(random.uniform(1, 3))
    

    5.2 使用代理IP

    若 IP 被封禁,可使用代理IP服务(如付费代理或免费代理池):

    proxies = {
        "http": "http://your_proxy_ip:port",
        "https": "http://your_proxy_ip:port"
    }
    response = requests.get(url, headers=headers, proxies=proxies)
    

    5.3 使用Session保持登录状态

    通过 requests.Session() 保持会话,减少重复登录的开销:

    session = requests.Session()
    session.headers.update(headers)
    response = session.get(url)
    

    第六部分:常见问题与解决方案

    6.1 Cookie失效

    现象:返回 403 状态码或空数据。
    解决方案:重新登录知乎并更新 Cookie 值。

    6.2 动态加载内容

    现象:页面内容为空或不完整。
    解决方案:改用 API 接口获取数据,或使用 Selenium 模拟浏览器操作。

    6.3 网络请求超时

    现象:请求无响应或超时。
    解决方案:设置超时时间并增加重试机制:

    try:
        response = requests.get(url, headers=headers, timeout=10)
    except requests.exceptions.Timeout:
        print("请求超时,重试...")
        response = requests.get(url, headers=headers, timeout=10)
    

    第七部分:完整代码整合

    7.1 静态HTML解析完整代码

    import requests
    from bs4 import BeautifulSoup
    
    def fetch_zhihu_hot_html():
        url = "https://www.zhihu.com/hot"
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Cookie": "你的知乎登录Cookie值"
        }
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.text
        else:
            print("页面获取失败")
            return None
    
    def parse_html(html):
        soup = BeautifulSoup(html, 'lxml')
        hot_items = soup.select('.HotList-list section')
        data = []
        for index, item in enumerate(hot_items, start=1):
            title = item.select_one('.HotItem-title').text.strip()
            link = item.select_one('a')['href']
            hot_value = item.select_one('.HotItem-meta').text.strip()
            data.append({
                "排名": index,
                "标题": title,
                "链接": f"https://www.zhihu.com{link}",
                "热度值": hot_value
            })
        return data
    
    def save_to_csv(data, filename="zhihu_hot_list.csv"):
        import pandas as pd
        df = pd.DataFrame(data)
        df.to_csv(filename, index=False, encoding="utf-8-sig")
        print(f"数据已保存为 {filename}")
    
    # 主程序
    if __name__ == "__main__":
        html = fetch_zhihu_hot_html()
        if html:
            data = parse_html(html)
            save_to_csv(data)
    

    7.2 API接口完整代码

    import requests
    import json
    import pandas as pd
    
    def fetch_zhihu_hot_api():
        api_url = "https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=50&desktop=true"
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Cookie": "你的知乎登录Cookie值",
            "Referer": "https://www.zhihu.com/hot"
        }
        response = requests.get(api_url, headers=headers)
        if response.status_code == 200:
            return response.json()
        else:
            print("API请求失败")
            return None
    
    def parse_json(json_data):
        data = []
        for idx, item in enumerate(json_data['data'], start=1):
            title = item['target']['title_area']['text']
            link = item['target']['content']['href']
            hot_value = item['hot_score']
            desc = item['target']['excerpt_area']['text']
            data.append({
                "排名": idx,
                "标题": title,
                "链接": f"https://www.zhihu.com{link}",
                "热度值": hot_value,
                "描述": desc
            })
        return data
    
    def save_to_csv(data, filename="zhihu_hot_api.csv"):
        df = pd.DataFrame(data)
        df.to_csv(filename, index=False, encoding="utf-8-sig")
        print(f"数据已保存为 {filename}")
    
    # 主程序
    if __name__ == "__main__":
        json_data = fetch_zhihu_hot_api()
        if json_data:
            data = parse_json(json_data)
            save_to_csv(data)
    

    结论

    通过本文的实战教程,读者可以掌握以下技能:

    1. 知乎热榜数据的两种爬取方法(HTML解析和API接口)。
    2. 反爬虫策略的应对技巧(设置请求头、使用代理IP、随机延迟)。
    3. 数据存储与可视化(CSV文件保存和Matplotlib图表绘制)。
    4. 代码模块化设计(函数封装和主程序调用)。

    需要注意的是,爬虫行为应遵守网站的 robots.txt 规则和法律法规,避免对服务器造成过载。建议在实际应用中合理控制请求频率,并尊重数据来源的版权。
    Python爬虫实战

    作者:yansideyucsdn

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python实战爬虫技巧:使用Requests库轻松爬取知乎热榜内容

    发表回复