Python Requests 的高级使用技巧:应对复杂 HTTP 请求场景

爬虫代理

介绍

网络爬虫(Web Crawler)是自动化的数据采集工具,用于从网络上提取所需的数据。然而,随着反爬虫技术的不断进步,很多网站增加了复杂的防护机制,使得数据采集变得更加困难。在这种情况下,Python 的 requests 库因其易用性和强大的功能,成为了开发爬虫的常用工具。然而,在复杂的 HTTP 请求场景中,标准的 requests 使用往往不够灵活,爬虫需要结合代理、会话控制、限流等高级技巧来更好地适应不同网站的反爬限制。

本文将针对三种典型的复杂 HTTP 请求场景,分别为 Spider Trap(蜘蛛陷阱)、SESSION访问限制和请求频率限制,进行深入的技术分析,并给出实际代码示例,帮助读者掌握 Python Requests 的高级用法。

技术分析

1. 应对 Spider Trap(蜘蛛陷阱)

Spider Trap 是一种通过设置大量链接或无限循环的链接结构来消耗爬虫资源的技术。爬虫陷入这些陷阱后,可能会在特定网页中无限循环,导致资源浪费,甚至引发封禁。为避免此问题,我们可以采取以下措施:

  • CSS类链接数控制:限制同一页面中每个 CSS 类中能爬取的最大链接数,从而防止在陷阱页面中过度抓取。
  • URL去重:通过哈希或布隆过滤器(Bloom Filter)对已访问的 URL 进行去重,避免重复抓取。

以下代码展示了如何通过 Python Requests 结合代理和 CSS 类链接数控制来实现对 Spider Trap 的防护。

import requests
from bs4 import BeautifulSoup
import hashlib

# 代理信息,需替换成实际的亿牛云爬虫代理配置 www.16yun.cn
proxy = {
    "http": "http://username:password@proxy.16yun.cn:18000",
    "https": "http://username:password@proxy.16yun.cn:18000"
}

# 用于记录访问过的URL
visited_urls = set()

# 爬取函数
def crawl(url, max_links_per_class=10):
    if url in visited_urls:
        print(f"已访问过 URL:{url}")
        return
    
    try:
        # 使用代理发送请求
        response = requests.get(url, proxies=proxy, timeout=10)
        response.raise_for_status()
        visited_urls.add(url)  # 标记该 URL 为已访问
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # 统计每个 CSS 类中的链接数
        class_link_count = {}

        for link in soup.find_all("a", href=True):
            # 计算每个链接的哈希值
            link_url = link['href']
            link_class = link.get("class", [""])[0]

            # 更新每个 CSS 类的链接数
            class_link_count[link_class] = class_link_count.get(link_class, 0) + 1

            # 超过最大链接数则跳过
            if class_link_count[link_class] > max_links_per_class:
                print(f"跳过过多链接的类:{link_class}")
                continue
            
            # 递归爬取新链接
            if link_url not in visited_urls:
                crawl(link_url)

    except requests.RequestException as e:
        print(f"请求失败:{e}")

# 开始爬取
crawl("http://example.com")

2. SESSION访问限制

某些网站会通过观察用户的操作模式来区分是普通用户还是爬虫。例如,频繁的请求和重复性高的操作可能被视为异常,导致账号被限制访问。针对这种情况,我们可以模拟用户的正常操作,比如在页面之间设置合理的等待时间,同时通过多个账号轮换访问来减少单一 SESSION 的负载。

以下代码示例展示了如何模拟多账号登录,并进行合理的延时,避免触发访问限制。

import requests
import time
import random

# 代理信息,需替换成实际的亿牛云爬虫代理配置 www.16yun.cn
proxy = {
    "http": "http://username:password@proxy.16yun.cn:18000",
    "https": "http://username:password@proxy.16yun.cn:18000"
}

# 用户账号列表
accounts = [
    {"username": "user1", "password": "pass1"},
    {"username": "user2", "password": "pass2"},
    # 可添加更多账号
]

def login(account):
    session = requests.Session()
    login_url = "http://example.com/login"
    
    try:
        # 使用POST方法模拟登录请求
        response = session.post(login_url, data=account, proxies=proxy)
        response.raise_for_status()
        
        # 检查登录状态
        if "欢迎" in response.text:
            print(f"{account['username']} 登录成功")
            return session
        else:
            print(f"{account['username']} 登录失败")
            return None

    except requests.RequestException as e:
        print(f"请求失败:{e}")
        return None

# 主循环
for account in accounts:
    session = login(account)
    if session:
        # 模拟正常操作,随机延时
        for _ in range(5):
            try:
                response = session.get("http://example.com/data", proxies=proxy)
                response.raise_for_status()
                print(f"获取数据:{response.text[:100]}...")
                
                # 模拟用户的延时
                time.sleep(random.uniform(1, 3))

            except requests.RequestException as e:
                print(f"请求失败:{e}")
                
    # 切换账号
    time.sleep(random.uniform(5, 10))

3. 请求频率限制

为了防止频繁请求造成服务器压力,很多网站设置了请求频率限制。常用的限流算法包括令牌桶漏桶。这些算法通过控制请求速度和时间间隔来实现稳定的数据请求。

以下示例展示了通过限流控制请求频率的方式,以避免触发请求频率限制。

import requests
import time
import threading
import queue

# 代理信息,需替换成实际的亿牛云爬虫代理配置 www.16yun.cn
proxy = {
    "http": "http://username:password@proxy.16yun.cn:18000",
    "https": "http://username:password@proxy.16yun.cn:18000"
}

# 配置令牌桶
class TokenBucket:
    def __init__(self, rate, capacity):
        self.rate = rate          # 每秒生成的令牌数
        self.capacity = capacity  # 桶的最大容量
        self.tokens = capacity
        self.last_refill_time = time.time()

    def acquire(self):
        current_time = time.time()
        elapsed = current_time - self.last_refill_time
        # 更新令牌数量
        self.tokens = min(self.capacity, self.tokens + elapsed * self.rate)
        self.last_refill_time = current_time

        # 判断是否可以进行请求
        if self.tokens >= 1:
            self.tokens -= 1
            return True
        else:
            return False

# 创建令牌桶,限制每秒最多3个请求
token_bucket = TokenBucket(rate=3, capacity=3)

def limited_request(url):
    while not token_bucket.acquire():
        time.sleep(0.1)  # 等待令牌
    try:
        response = requests.get(url, proxies=proxy)
        print(f"获取数据:{response.text[:100]}...")
    except requests.RequestException as e:
        print(f"请求失败:{e}")

# 测试请求
urls = ["http://example.com/data"] * 10
for url in urls:
    threading.Thread(target=limited_request, args=(url,)).start()

结论

本文深入探讨了 Python Requests 的高级使用技巧,帮助读者在面对复杂的 HTTP 请求场景时更加得心应手。通过代理的使用、CSS 类链接数控制、多账号 SESSION 切换、以及限流算法的实现,我们可以大幅提高爬虫的稳定性与效率,提升在反爬虫环境中的生存能力。掌握这些技巧不仅有助于提高抓取数据的成功率,同时也为更复杂的反爬需求打下了扎实的技术基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/905604.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux中NFS配置

文章目录 一、NFS介绍1.1、NFS的工作流程1.2、NFS主要涉及的软件包1.3、NFS的主要配置文件 二、安装NFS2.1、更新yum2.2、安装NFS服务2.3、配置NFS服务器2.4、启动NFS服务2.5、配置防火墙(如果启用了防火墙,需要允许NFS相关的端口通过)2.6、生…

MATLAB发票识别系统

课题介绍 该课题为基于MATLAB的发票识别系统。主要识别发票的编号。可定做发票的日期,金额等字段的识别。通过输入图片,校正,定位目标区域,分割,字符分割,模板匹配识别,得出结果。整个设计包含…

前端拖拽库方案之react-beautiful-dnd

近期,知名 React 拖拽库 react-beautiful-dnd 宣布了项目弃用的决定,未来将不再维护。这一决定源于其存在的缺陷与局限性,促使作者转向开发一个更加现代化的拖拽解决方案——Pragmatic drag and drop(下面会介绍)&…

Rust 力扣 - 643. 子数组最大平均数 I

文章目录 题目描述题解思路题解代码题解链接 题目描述 题解思路 我们遍历长度为k的窗口&#xff0c;我们只需要记录窗口内的最大和即可&#xff0c;遍历过程中刷新最大值 结果为窗口长度为k的最大和 除以 k 题解代码 impl Solution {pub fn find_max_average(nums: Vec<…

Linux——五种IO模型

目录 一IO基本理解 二五种IO模型 1五种IO模型示意图 2同步IO和异步IO 二非阻塞IO 1fcntl 2实现非阻塞IO 三多路复用 1select 1.1定位和作用 1.2介绍参数 1.3编写多路复用代码 1.4优缺点 2poll 2.1作用和定位 2.2介绍参数 2.3修改select代码 3epoll 3.1介绍…

php解密,sg11解密-sg15解密 如何由sourceGuardian11-sourceGuardian15加密(sg11加密~sg15加密)的源码

sg11加密~sg11加密的PHP文件运行需安装SG11加密-SG15加密组件使用、支持WINDOW及LINUX各版本 sg11解密(SourceGuardian)-sg15解密(SourceGuardian)&#xff0c;号称目前最安全的组件加密已可以解密&#xff0c;解密率99.9%&#xff0c;基本可以直接使用&#xff0c;代码特征是…

Jetson OrinNX平台CSI相机导致cpu load average升高问题调试

1. 前言 硬件: Orin NX JP: 5.1.2, R35.4.1 用v4l2-ctl --stream-mmap -d0 命令去获取相机数据时, 用top查看cpu使用情况, CPU占用率很低,但load average在1左右, 无任何程序运行时,load average 为0 用ps -aux 查看当前进程情况,发现有两个系统进程vi-output, …

qt QIcon详解

1、概述 QIcon是Qt框架中的一个类&#xff0c;专门用于处理和显示图标。它提供了灵活的接口&#xff0c;支持从多种来源加载图标&#xff0c;如文件、资源或系统主题&#xff0c;并且支持多种图像格式&#xff0c;如PNG、JPEG、SVG等。QIcon类能够与Qt中的各种控件&#xff08…

【操作系统实验课】Linux操作基础

1. 打开Ubuntu Ubuntu-22.04 虚拟机安装-CSDN博客 打开虚拟机软件 启动其中的Ubuntu22.04 打开Ubuntu系统终端 2. 创建目录和文件 创建test3目录&#xff1a; 在终端中输入命令&#xff1a;mkdir /test3。此命令用于在根目录下创建test3目录。&#xff08;注意在命令中&…

【Linux-进程间通信】匿名管道的应用-进程池实现+命名管道的应用ClientServer通信

匿名管道的应用--进程池/C实现 当系统中需要处理众多任务时&#xff0c;可以将这些任务分配给多个子进程来分担工作。然而&#xff0c;频繁地创建和销毁进程会导致较高的时间成本。为减少这种开销&#xff0c;可以采取预先创建一组子进程的策略&#xff08;以避免在任务分配时…

java设计模式之创建者模式(5种)

设计模式 软件设计模式&#xff0c;又称为设计模式&#xff0c;是一套被反复利用&#xff0c;代码设计经验的总结&#xff0c;他是在软件设计过程中的一些不断发生的问题&#xff0c;以及该问题的解决方案。 **创建者模式又分为以下五个模式&#xff1a;**用来描述怎么“将对象…

数据库->数据库约束

目录 一、数据库约束 1.定义 2.约束类型 3.NOT NULL 非空约束 4. UNIQUE 唯一约束 5.PRIMARY KEY 主键约束 1.主键的使用 2.把表中的主键交给数据库自己维护 2.1主键列设置为null 则使用自增 2.2插入除了主键以外的所有非空列&#xff08;推荐方法&#xff09; 2.3自…

ValueError: Object arrays cannot be loaded when allow_pickle=False

文章目录 问题解决方法1&#xff1a;allow_pickleTrue解决方法2&#xff1a;降低numpy版本错误原因&#xff1a;python和numpy版本不兼容 问题 Traceback (most recent call last): File “D:\project\test_st\retrieval\read_npy.py”, line 4, in data np.load(‘mosi0__le…

HTML CSS

目录 1. 什么是HTML 2. 什么是CSS ? 3. 基础标签 & 样式 3.1 新浪新闻-标题实现 3.1.1 标题排版 3.1.1.1 分析 3.1.1.2 标签 3.1.1.3 实现 3.1.2 标题样式 3.1.2.1 CSS引入方式 3.1.2.2 颜色表示 3.1.2.3 标题字体颜色 3.1.2.4 CSS选择器 3.1.2.5 发布时间字…

Prometheus和Grafana的安装部署

初识Prometheus和Grafana 通常来说&#xff0c;对于一个运行时的复杂系统&#xff0c;如果系统出了问题是很难排查的。因为你是不太可能在运行时一边检查代码一边调试的。因此&#xff0c;你需要在各种关键点加上监控&#xff0c;通过监控获取的数据&#xff0c;指导我们进一步…

ubuntu20.04 加固方案-设置用户缺省UMASK

一、编辑/etc/profile配置文件 打开终端。 查看当前umask 使用文本编辑器&#xff08;如vim&#xff09;编辑/etc/profile文件。 sudo vim /etc/profile 二、添加配置参数 在打开的配置文件的末尾中&#xff0c;添加或修改以下参数&#xff1a; umask 027 三、保存并退出…

liunx网络套接字 | 实现基于tcp协议的echo服务

前言&#xff1a;本节讲述linux网络下的tcp协议套接字相关内容。博主以实现tcp服务为主线&#xff0c;穿插一些小知识点。以先粗略实现&#xff0c;后精雕细琢为思路讲述实现服务的过程。下面开始我们的学习吧。 ps&#xff1a;本节内容建议了解网络端口号的友友们观看哦。 目录…

【果蔬识别】Python+卷积神经网络算法+深度学习+人工智能+机器学习+TensorFlow+计算机课设项目+算法模型

一、介绍 果蔬识别系统&#xff0c;本系统使用Python作为主要开发语言&#xff0c;通过收集了12种常见的水果和蔬菜&#xff08;‘土豆’, ‘圣女果’, ‘大白菜’, ‘大葱’, ‘梨’, ‘胡萝卜’, ‘芒果’, ‘苹果’, ‘西红柿’, ‘韭菜’, ‘香蕉’, ‘黄瓜’&#xff09;…

isp框架代码理解

一、整体框架如下&#xff1a; 1 外层的src中 1.1 从camera.c->task.c&#xff1a;封装了3层&#xff0c;透传到某个功能的本级。 1.2 core.c和capability.c中实现&#xff1a;开机初始化加载参数。2. plat/src中 2.1 fun.c中继task.c又透传了一层&#xff1b;以及最后功能…

VuePress文档初始化请求过多问题探讨

1. 背景 公司有部门使用VuePress 1.0搭建平台的帮助文档&#xff0c;前期文档不是很多&#xff0c;所以没有暴露出特别明显的问题。但随着文档的逐步迭代和内容的增多&#xff0c;出现了大量的并发请求&#xff0c;总共有218个请求&#xff0c;导致服务器带宽耗尽、响应速度下降…