构建稳定爬虫:为番茄小说爬虫添加IP代理与请求头伪装

小白学大数据
• 阅读 3

一、 引言:为何我们的爬虫会被“封杀”? 当我们兴致勃勃地编写好一个爬虫脚本,初期运行顺畅,但很快便会遭遇 403 Forbidden、429 Too Many Requests,甚至IP被直接封禁的窘境。这背后,是网站防御系统对我们发起的挑战: 频率特征:同一IP在短时间内发起大量请求,行为明显异于正常人类用户。 指纹特征:使用默认的requests或urllib库的User-Agent,服务器可轻易识别出这是爬虫程序。 行为模式:缺乏有效的Cookie、Referer等头部信息,访问路径单一。 要解决这些问题,我们的核心策略是:让爬虫尽可能地模拟真实用户的访问行为。这其中的两大基石便是IP代理与请求头伪装。 二、 核心技术一:请求头伪装 - 成为“浏览器”而非“脚本” 请求头是HTTP请求的“身份证”,它向服务器传递了客户端的详细信息。我们的首要任务就是为爬虫伪造一张合法的“身份证”。

  1. 基础伪装:设置User-Agent User-Agent是标识浏览器类型和版本的最关键字段。

一个简单的伪装示例(不推荐用于生产)

headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' } response = requests.get('https://fanqienovel.com', headers=headers)

2. 高级伪装:构建完整的浏览器指纹
一个真实的浏览器请求会携带数十个头部字段。仅设置User-Agent是远远不够的。
``` def create_headers():
    """
    创建一个完整的、随机的请求头字典
    """
    # 准备多个常见的User-Agent,实现随机轮换
    user_agents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0'
    ]
    import random
    chosen_ua = random.choice(user_agents)

    headers = {
        'User-Agent': chosen_ua,
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', # 语言偏好
        'Accept-Encoding': 'gzip, deflate, br',
        'Referer': 'https://www.douyin.com/', # 模拟从其他网站跳转而来
        'Sec-Ch-Ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', # 客户端提示
        'Sec-Ch-Ua-Mobile': '?0',
        'Sec-Ch-Ua-Platform': '"Windows"',
        'Sec-Fetch-Dest': 'document',
        'Sec-Fetch-Mode': 'navigate',
        'Sec-Fetch-Site': 'none',
        'Upgrade-Insecure-Requests': '1',
        'Connection': 'keep-alive',
        'Cache-Control': 'max-age=0',
    }
    return headers

# 使用自定义头部发起请求
headers = create_headers()
response = requests.get('https://fanqienovel.com/page/example', headers=headers)

关键点:Referer字段尤为重要,它告诉服务器当前请求是从哪个页面链接过来的,模拟用户的连续浏览行为。 三、 核心技术二:IP代理 - 打造“千面”爬虫 即使请求头伪装得再好,来自单一IP的高频请求依然会暴露。使用IP代理池,让请求来自全球各地的不同机器,是突破IP封锁的根本手段。

  1. 获取代理IP 代理IP的来源主要有以下几类: 免费代理:缺点是稳定性差、可用率低,仅适用于测试。 付费代理服务:提供高匿、稳定的HTTP/HTTPS/SOCKS5代理,通常通过API接口获取IP列表,是商业项目的首选。 自建代理池:通过扫描公网或云服务器自建,技术门槛和成本较高,但控制力最强。
  2. 构建IP代理池管理器 我们将创建一个类来管理代理IP,包括获取、验证、轮换和剔除失效IP。
    import random
    import time
    

class ProxyPoolManager: def init(self, proxy_source_url=None): self.proxy_source_url = proxy_source_url # 付费代理服务商提供的API地址 self.proxies_pool = [] # 代理池 self.last_fetch_time = 0 self.fetch_interval = 600 # 10分钟更新一次代理池

def fetch_proxies(self):
    """从代理服务商API获取代理IP列表"""
    if time.time() - self.last_fetch_time < self.fetch_interval and self.proxies_pool:
        return # 未到更新时间且池子不为空,则不更新

    try:
        # 示例:调用代理服务商API
        resp = requests.get(self.proxy_source_url, timeout=10)
        if resp.status_code == 200:
            # 假设API返回JSON格式: [{"ip": "1.2.3.4", "port": "8080"}, ...]
            new_proxies = resp.json()
            # 格式化为requests库需要的格式
            formatted_proxies = [f"http://{p['ip']}:{p['port']}" for p in new_proxies]
            self.proxies_pool = formatted_proxies
            self.last_fetch_time = time.time()
            print(f"成功更新代理池,当前共有 {len(self.proxies_pool)} 个代理IP。")
    except Exception as e:
        print(f"获取代理IP失败: {e}")

def validate_proxy(self, proxy_url, test_url='https://httpbin.org/ip', timeout=5):
    """验证单个代理IP是否有效"""
    try:
        proxies = {'http': proxy_url, 'https': proxy_url}
        response = requests.get(test_url, proxies=proxies, timeout=timeout)
        if response.status_code == 200:
            # 检查返回的IP是否确实是代理IP
            returned_ip = response.json().get('origin')
            proxy_ip = proxy_url.split('//')[1].split(':')[0]
            if returned_ip == proxy_ip:
                print(f"代理 {proxy_url} 验证有效。")
                return True
    except Exception as e:
        # 代理无效,静默失败或记录日志
        pass
    print(f"代理 {proxy_url} 验证无效,已剔除。")
    return False

def get_random_valid_proxy(self):
    """获取一个随机的、经过验证的有效代理"""
    self.fetch_proxies() # 确保代理池是最新的

    if not self.proxies_pool:
        raise Exception("代理池为空,无法获取代理。")

    # 随机选择一个代理
    proxy = random.choice(self.proxies_pool)

    # 验证该代理
    if self.validate_proxy(proxy):
        return proxy
    else:
        # 如果无效,从池中移除并重试
        self.proxies_pool.remove(proxy)
        return self.get_random_valid_proxy() # 递归调用,直到找到有效的
3. 集成IP代理与请求头伪装
现在,我们将两大技术整合到番茄小说爬虫的核心请求函数中。
```import requests
            try:
                print(f"第 {attempt + 1} 次尝试请求: {url}")
                response = session.request(method, url, **kwargs)

                # 检查响应状态和内容
                if response.status_code == 200:
                    if "验证码" not in response.text and "access denied" not in response.text.lower():
                        print("请求成功!")
                        return response
                    else:
                        print("请求可能被反爬系统拦截,检测到验证码页面")
                else:
                    print(f"请求失败,状态码: {response.status_code}")

            except (requests.exceptions.ProxyError, 
                    requests.exceptions.ConnectTimeout, 
                    requests.exceptions.ReadTimeout,
                    requests.exceptions.ConnectionError) as e:
                print(f"第 {attempt + 1} 次请求失败: {e}")
                if attempt < max_retries - 1:
                    wait_time = 2 ** attempt  # 指数退避策略
                    print(f"等待 {wait_time} 秒后重试...")
                    time.sleep(wait_time)
                    continue
                else:
                    print("所有重试均失败")
                    raise e

            # 如果不是网络错误,但请求被拦截,也进行重试
            if attempt < max_retries - 1:
                wait_time = 2 ** attempt
                print(f"请求可能被拦截,等待 {wait_time} 秒后重试...")
                time.sleep(wait_time)

        return None

    # 为session绑定新的方法
    session.robust_request = _make_request
    return session

# 主爬虫函数
def crawl_fanqie_novel(book_id):
    """爬取番茄小说内容"""
    # 初始化代理池管理器
    proxy_manager = ProxyPoolManager()

    # 创建稳健的Session
    session = create_robust_session(proxy_manager)

    # 构造目标URL
    url = f'https://fanqienovel.com/reader/{book_id}'
    print(f"开始爬取: {url}")

    try:
        # 使用我们自定义的稳健请求方法
        response = session.robust_request(url)

        if response and response.status_code == 200:
            # 此处接续你的HTML解析逻辑
            print("成功获取页面内容!")
            # 可以在这里添加内容解析代码
            # soup = BeautifulSoup(response.text, 'html.parser')
            # ... 解析逻辑
            return response.text
        else:
            print("爬取失败,请检查网络或反爬策略。")
            return None

    except Exception as e:
        print(f"爬虫执行过程中发生错误: {e}")
        return None

# 使用示例
if __name__ == "__main__":
    # 测试爬虫
    book_id = '123456789012345'
    result = crawl_fanqie_novel(book_id)

    if result:
        print("爬取成功!")
        # 处理爬取到的内容
    else:
        print("爬取失败!")

四、 高级策略与最佳实践 请求频率控制:在关键请求之间使用time.sleep(random.uniform(1, 3)),模拟人类阅读的随机间隔。 会话保持:对于需要登录或保持状态的任务,使用requests.Session()对象,它会自动处理Cookies。 CAPTCHA处理:当遭遇验证码时,可以:a) 使用第三方打码平台;b) 临时切换更高匿名度的代理;c) 暂停爬虫一段时间。 监控与日志:记录每个请求使用的代理、耗时、状态码,便于分析代理质量和网站反爬策略的变化。 五、 总结 通过系统地集成请求头伪装与IP代理池,我们的番茄小说爬虫成功地从一只容易被拍死的“苍蝇”,进化成了一个拥有无数伪装身份的“特工”。这不仅是技术的叠加,更是一种工程思维的体现:将爬虫系统视为一个需要持续对抗、适应和演化的有机体。

点赞
收藏
评论区
推荐文章
美凌格栋栋酱 美凌格栋栋酱
10个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
菜鸟阿都 菜鸟阿都
4年前
创建免费ip代理池
&ensp;&ensp;&ensp;&ensp; 反爬技术越来越成熟,为了爬取目标数据,必须对爬虫的请求进行伪装,骗过目标系统,目标系统通过判断请求的访问频次或请求参数将疑似爬虫的ip进行封禁,要求进行安全验证,通过python的第三方库faker可以随机生成header伪装请求头,并且减缓爬虫的爬取速度,能很好的避过多数目标系统的反扒机制,但对一些安全等级
Stella981 Stella981
4年前
Python爬虫代理池
爬虫代理IP池在公司做分布式深网爬虫,搭建了一套稳定的代理池服务,为上千个爬虫提供有效的代理,保证各个爬虫拿到的都是对应网站有效的代理IP,从而保证爬虫快速稳定的运行,当然在公司做的东西不能开源出来。不过呢,闲暇时间手痒,所以就想利用一些免费的资源搞一个简单的代理池服务。1、问题代理IP从何而来?
Stella981 Stella981
4年前
Nginx反爬虫: 禁止某些User Agent抓取网站
一、概述网站反爬虫的原因不遵守规范的爬虫会影响网站的正常使用网站上的数据是公司的重要资产爬虫对网站的爬取会造成网站统计数据的污染常见反爬虫手段1\.根据IP访问频率封禁IP2\.设置账号登陆时长,账号访问过多封禁设置账号的登录限制,只有登录才能展现内容
Stella981 Stella981
4年前
Selenium使用代理出现弹窗验证如何处理
部分商业网站对爬虫程序限制较多,在数据采集的过程中对爬虫请求进行了多种验证,导致爬虫程序需要深入分析目标网站的反爬策略,定期更新和维护爬虫程序,增加了研发的时间和投入成本。这种情况下,使用无头浏览器例如Selenium,模拟用户的请求进行数据采集是更加方便快捷的方式。同时为了避免目标网站出现IP限制,配合爬虫代理,实现每次请求自动切换IP,能够保证长期稳定
突破反爬:使用代理IP和User-Agent轮询爬取音乐数据
一、反爬虫机制的原理与应对策略在深入技术实现之前,我们有必要了解常见的反爬虫机制及其工作原理:1.IP频率限制:网站会监控单个IP地址的请求频率,如果短时间内请求过多,会判定为该IP存在爬虫行为,从而实施封禁。2.UserAgent检测:通过检查HTTP请
爬虫中使用代理IP的一些误区
做为爬虫工作者在日常工作中使用爬虫多次爬取同一网站时,经常会被网站的IP反爬虫机制给禁掉,为了解决封禁IP的问题通常会使用代理IP。但也有一部分人在HTTP代理IP的使用上存在着误解,他们认为使用了代理IP就能解决一切问题,然而实际上代理IP不是万
爬虫代理IP是什么?为什么需要它?
爬虫代理IP是什么?为什么需要它?爬虫代理IP是指使用其他计算机的网络地址来访问目标网站的一种技术。它可以隐藏爬虫程序的真实IP地址,避免被网站识别和封禁12。在进行网络数据采集时,我们经常会遇到一些反爬措施,比如网站限制同一个IP地址的访问频率、次数或时
小白学大数据 小白学大数据
5个月前
如何通过requests和time模块限制爬虫请求速率?
一、为什么需要限制爬虫请求速率?在爬取网站数据时,网站服务器需要处理我们的请求并返回数据。如果爬虫的请求过于频繁,服务器可能会因为负载过高而崩溃,或者将我们的爬虫IP地址封禁。此外,许多网站都有反爬虫机制,例如检测单位时间内来自同一IP的请求频率。如果请求
小白学大数据
小白学大数据
Lv1
男 · 亿牛云 · python技术
宁为代码类弯腰,不为bug点提交!
文章
125
粉丝
5
获赞
18