Python爬虫技术 第22节 反爬虫机制及对策

news2024/9/8 23:58:27

反爬虫机制是网站为了防止自动化工具抓取其内容而采取的各种技术和策略。了解这些机制可以帮助你设计更有效的爬虫程序。下面我将详细讲解常见的反爬虫机制及其应对策略。

常见的反爬虫机制

  1. IP 封禁

    • 描述:服务器检测到某个 IP 地址在短时间内发送了大量的请求,会将其列入黑名单。
    • 对策
      • 使用代理池轮换 IP 地址。
      • 限制请求频率,模拟真实用户的访问行为。
  2. User-Agent 检测

    • 描述:服务器会检查 User-Agent 字段,如果发现是爬虫常用的 User-Agent,则拒绝服务。
    • 对策
      • 使用随机或伪装的 User-Agent。
      • 模拟常见浏览器的 User-Agent。
  3. 验证码(CAPTCHA)

    • 描述:当检测到可疑行为时,网站会要求用户输入验证码。
    • 对策
      • 使用 OCR 技术识别验证码。
      • 使用第三方服务解决验证码问题。
      • 手动输入验证码。
  4. JavaScript 渲染

    • 描述:有些网站使用 JavaScript 动态加载内容,直接抓取 HTML 无法获取完整数据。
    • 对策
      • 使用支持 JavaScript 渲染的工具,例如 Selenium 或 Puppeteer。
      • 分析 JavaScript 代码,手动模拟请求。
  5. 动态 URL 生成

    • 描述:网站可能使用动态生成的 URL 来混淆爬虫。
    • 对策
      • 分析 URL 生成规律,手动构造 URL。
      • 使用 Selenium 等工具抓取动态生成的 URL。
  6. Cookie 和 Session ID

    • 描述:网站可能通过 Cookie 和 Session ID 进行跟踪。
    • 对策
      • 保持会话状态,使用相同的 Cookie 和 Session ID。
      • 使用轮换的 Cookie 和 Session ID。
  7. HTTP 请求头检查

    • 描述:服务器会检查 HTTP 请求头中的字段,如 Accept-Language、Referer 等。
    • 对策
      • 模拟真实的请求头信息。
      • 使用随机或真实的请求头。
  8. 限制请求频率

    • 描述:服务器会对每个 IP 或会话的请求数量进行限制。
    • 对策
      • 添加延时以降低请求频率。
      • 使用代理池轮换 IP 地址。
  9. 隐藏数据

    • 描述:有些网站会隐藏关键数据,只在特定条件下显示。
    • 对策
      • 分析网页结构和交互逻辑。
      • 发送特定的请求来触发数据展示。
  10. 法律限制

    • 描述:有些网站会在 robots.txt 文件或服务条款中禁止爬虫。
    • 对策
      • 遵守网站的爬虫政策。
      • 获得网站所有者的明确许可。

应对策略示例代码

1. 使用代理池
import requests
from random import choice

proxies = [
    "http://proxy1.example.com:8080",
    "http://proxy2.example.com:8080",
    "http://proxy3.example.com:8080"
]

def get_with_proxy(url):
    proxy = {"http": choice(proxies), "https": choice(proxies)}
    try:
        response = requests.get(url, proxies=proxy, timeout=5)
        return response
    except Exception as e:
        print(f"Failed to fetch {url}: {e}")
        return None

response = get_with_proxy("https://example.com")
if response:
    print(response.text)
2. 使用随机 User-Agent
import requests
from fake_useragent import UserAgent

ua = UserAgent()

def get_with_random_ua(url):
    headers = {'User-Agent': ua.random}
    try:
        response = requests.get(url, headers=headers, timeout=5)
        return response
    except Exception as e:
        print(f"Failed to fetch {url}: {e}")
        return None

response = get_with_random_ua("https://example.com")
if response:
    print(response.text)
3. 使用 Selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def get_with_selenium(url):
    driver = webdriver.Chrome()
    driver.get(url)
    try:
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "some_id"))
        )
        print(element.text)
    finally:
        driver.quit()

get_with_selenium("https://example.com")

总结

  • 了解网站使用的反爬虫机制有助于你设计更有效的爬虫程序。
  • 采用合理的策略可以减少被封禁的风险,同时提高爬虫的稳定性和效率。
  • 在进行爬虫开发时,一定要遵守相关法律法规,尊重网站的服务条款。

接下来我会给出一些具体的代码案例,来演示如何处理一些常见的反爬虫机制。这里我们将重点介绍以下几个方面:

  1. 使用代理池
  2. 随机化 User-Agent
  3. 处理 JavaScript 渲染页面
  4. 处理验证码

当然可以!接下来,我将进一步优化之前的代码示例,以提高它们的稳定性和效率。我们将包括更完善的错误处理、重试机制、日志记录以及其他实用的功能。

1. 使用代理池

import requests
from random import choice
import logging
from time import sleep

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 代理池列表
proxies = [
    "http://proxy1.example.com:8080",
    "http://proxy2.example.com:8080",
    "http://proxy3.example.com:8080"
]

def get_with_proxy(url, max_retries=3):
    retries = 0
    while retries < max_retries:
        try:
            # 随机选择一个代理
            proxy = {"http": choice(proxies), "https": choice(proxies)}
            
            # 发送带有代理的请求
            response = requests.get(url, proxies=proxy, timeout=5)
            return response
        except Exception as e:
            retries += 1
            logging.warning(f"Failed to fetch {url} using proxy. Retry {retries}/{max_retries}. Error: {e}")
            sleep(1)  # 等待一秒后重试
    logging.error(f"Max retries reached for {url} using proxy.")
    return None

# 测试
url = "https://httpbin.org/ip"
response = get_with_proxy(url)

if response:
    print(response.text)

2. 随机化 User-Agent

import requests
from fake_useragent import UserAgent
import logging
from time import sleep

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 创建 UserAgent 对象
ua = UserAgent()

def get_with_random_ua(url, max_retries=3):
    retries = 0
    while retries < max_retries:
        try:
            # 设置随机的 User-Agent
            headers = {'User-Agent': ua.random}
            
            # 发送带有随机 User-Agent 的请求
            response = requests.get(url, headers=headers, timeout=5)
            return response
        except Exception as e:
            retries += 1
            logging.warning(f"Failed to fetch {url} using random UA. Retry {retries}/{max_retries}. Error: {e}")
            sleep(1)  # 等待一秒后重试
    logging.error(f"Max retries reached for {url} using random UA.")
    return None

# 测试
url = "https://httpbin.org/headers"
response = get_with_random_ua(url)

if response:
    print(response.text)

3. 处理 JavaScript 渲染页面

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import logging
from time import sleep

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def get_with_selenium(url, max_retries=3):
    retries = 0
    while retries < max_retries:
        try:
            # 配置 Chrome 选项
            chrome_options = Options()
            chrome_options.add_argument("--headless")  # 无头模式
            
            # 初始化 WebDriver
            driver = webdriver.Chrome(options=chrome_options)
            
            try:
                # 访问目标网址
                driver.get(url)
                
                # 等待某个元素加载完成
                element = WebDriverWait(driver, 10).until(
                    EC.presence_of_element_located((By.ID, "some_element_id"))
                )
                
                # 获取页面源码
                page_source = driver.page_source
                
                # 输出页面源码
                logging.info("Page source retrieved successfully.")
                return page_source
            finally:
                # 关闭 WebDriver
                driver.quit()
            return page_source
        except Exception as e:
            retries += 1
            logging.warning(f"Failed to fetch {url} using Selenium. Retry {retries}/{max_retries}. Error: {e}")
            sleep(1)  # 等待一秒后重试
    logging.error(f"Max retries reached for {url} using Selenium.")
    return None

# 测试
url = "https://www.example.com"
page_source = get_with_selenium(url)

if page_source:
    print(page_source)

4. 处理验证码

验证码处理通常较为复杂,这里使用了一个简单的 OCR 解决方案作为示例。请注意,实际应用中可能需要更复杂的 OCR 处理或者使用专门的服务来处理验证码。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from PIL import Image
import pytesseract
from io import BytesIO
import logging
from time import sleep

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def solve_captcha(driver, captcha_element, max_retries=3):
    retries = 0
    while retries < max_retries:
        try:
            location = captcha_element.location
            size = captcha_element.size
            screenshot = driver.get_screenshot_as_png()
            im = Image.open(BytesIO(screenshot))
            left = location['x']
            top = location['y']
            right = location['x'] + size['width']
            bottom = location['y'] + size['height']
            im = im.crop((left, top, right, bottom))
            captcha_text = pytesseract.image_to_string(im)
            return captcha_text.strip()
        except Exception as e:
            retries += 1
            logging.warning(f"Failed to solve captcha. Retry {retries}/{max_retries}. Error: {e}")
            sleep(1)  # 等待一秒后重试
    logging.error("Max retries reached for solving captcha.")
    return None

def get_with_captcha(url, max_retries=3):
    retries = 0
    while retries < max_retries:
        try:
            # 初始化 WebDriver
            driver = webdriver.Chrome()
            
            try:
                # 访问目标网址
                driver.get(url)
                
                # 等待验证码出现
                captcha_element = WebDriverWait(driver, 10).until(
                    EC.presence_of_element_located((By.ID, "captcha_image"))
                )
                
                # 解析验证码
                captcha_text = solve_captcha(driver, captcha_element)
                
                # 打印解析出的验证码
                logging.info(f"Solved captcha: {captcha_text}")
                
                # 假设有一个输入框用于提交验证码
                input_field = WebDriverWait(driver, 10).until(
                    EC.presence_of_element_located((By.ID, "captcha_input"))
                )
                input_field.send_keys(captcha_text)
                
                # 提交表单或点击按钮
                submit_button = WebDriverWait(driver, 10).until(
                    EC.element_to_be_clickable((By.ID, "submit_button"))
                )
                submit_button.click()
                
                # 等待页面加载完成
                WebDriverWait(driver, 10).until(
                    EC.presence_of_element_located((By.ID, "content_after_captcha"))
                )
                
                # 获取页面源码
                page_source = driver.page_source
                
                # 输出页面源码
                logging.info("Page source retrieved successfully.")
                return page_source
            finally:
                # 关闭 WebDriver
                driver.quit()
            return page_source
        except Exception as e:
            retries += 1
            logging.warning(f"Failed to fetch {url} using captcha. Retry {retries}/{max_retries}. Error: {e}")
            sleep(1)  # 等待一秒后重试
    logging.error(f"Max retries reached for {url} using captcha.")
    return None

# 测试
url = "https://www.example.com/captcha"
page_source = get_with_captcha(url)

if page_source:
    print(page_source)

功能说明

  1. 错误处理:每个函数都包含了错误处理逻辑,可以捕获异常并记录日志。
  2. 重试机制:增加了重试机制,当请求失败时可以尝试多次。
  3. 日志记录:使用 logging 库记录爬虫的状态和错误信息,包括重试次数和最终失败的情况。
  4. 等待时间:在重试之间添加了等待时间,以减少服务器的压力。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt Designer,仿作一个ui界面的练习(一):界面的基本布局

初学不要太复杂&#xff0c;先做一个结构简单的&#xff0c;大致规划一下功能分区&#xff0c;绘制草图&#xff1a; 最终的效果&#xff1a; 界面主要由顶边栏、侧边栏、内容区构成。顶边栏左边是logo&#xff0c;右边是时钟显示。侧边栏最上边是切换按钮&#xff0c;用以动画…

Notcoin 即将空投:你需要知道什么

Notcoin 于 2024 年 1 月推出&#xff0c;是 Telegram 上的一款边玩边赚游戏&#xff0c;用户可以通过点击硬币图标获得 Notcoin 代币 (NOT) 形式的奖励。NOT 建立在开放网络区块链&#xff08;称为“TON 区块链”&#xff09;上&#xff0c;由 Open Builders 创始人 Sasha Plo…

鸿蒙配置Version版本号,并获取其值

app.json5中配置版本号&#xff1a; 获取版本号&#xff1a; bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).then((bundleInfo) > {let versionName bundleInfo.versionName; //应用版本号}).catch((error: BusinessE…

基于web的跨校区通勤车班次规划系统/校车管理系统

获取源码联系方式请查看文章结尾&#x1f345; 摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而…

STM32项目分享:智能台灯(机智云)系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; https://www.bilibili.com/video/BV1My411q7fE…

常见的CSS属性(一)——字体、文本、边框、内边距、外边距、背景、行高、圆角、透明度、颜色值

一、字体 二、文本 三、边框 四、外边距 五、内边距 六、背景 七、行高 八、圆角 九、透明度 九、颜色值 元素的继承性是指给父元素设置了某些属性&#xff0c;子元素或后代元素也会有作用。 一、字体 “font-*”是字体相关的属性&#xff0c;具有继承性。代码如下&a…

长上下文语言模型与RAPTOR 方法

在科技领域的前沿&#xff0c;长上下文语言模型&#xff08;Long Context LLMs&#xff09;和新兴检索方法如RAPTOR 正在引发广泛关注。本文将围绕这些技术展开讨论&#xff0c;并探讨它们在实际应用中的创新性和科技性。 长上下文语言模型的崛起 近几周来&#xff0c;随着新型…

基于 SSM 的汽车租赁系统

基于 SSM 的电器网上订购系统 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Spring、JSP、MyBatis 工具&#xff1a;MyEclipse/IDEA、Tomcat 引言 汽车租赁是在约定时间内&#xff0c;租赁经营人将租赁汽车&#xff08;包括载货汽车和载客汽车&#x…

前端在浏览器总报错,且获取请求头中token的值为null

前端请求总是失败说受跨域请求影响&#xff0c;但前后端配置已经没有问题了&#xff0c;如下&#xff1a; package com.example.shop_manage_sys.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Conf…

paddle ocr 文字识别模型训练 svtr

训练模型方法参考&#xff1a;https://github.com/PaddlePaddle/PaddleOCR/blob/main/doc/doc_ch/recognition.md 实践&#xff1a;https://aistudio.baidu.com/projectdetail/4482681 SVTR 算法原理 SVTR: Scene Text Recognition with a Single Visual Model Yongkun Du a…

Linux网络-ss命令

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注我&#xff0c;我尽量把自己会的都分享给大家&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux服务器作为一个常用的网络服务器&#xff0c;主要的作用就是向客户端提供网络…

数据结构(邓俊辉)学习笔记】高级搜索树03——红黑树

文章目录 1. 动机1.1 观察体验1.2 持久性1.3 关联性1.4 O&#xff08;1&#xff09;重构 2. 结构2.1 定义规则2.2 实例验证2.3 提升交换2.4 末端节点2.5 红黑树&#xff0c;即是B树2.6 平衡性2.7 接口定义 3. 插入3.1 以曲为直3.2 双红缺陷3.3 算法框架3.4 RR-13.5 RR-23.6 归纳…

将nvim的配置 上传gitee

首先是创建仓库 接着进入这个界面 然后是上传代码&#xff0c; 结果&#xff1a; 可以看到已经是可以了。 然后是 拉取代码进行测试。 第一次 拉取 使用 git clone .&#xff08;家里&#xff09; 做一点修改&#xff0c;然后上传。&#xff08;公司&#xff09; 然后在git pu…

Kotlin 的优势:现代编程语言的卓越选择

文章目录 简洁与优雅的语法空安全特性函数式编程&#xff0c;支持高阶函数、lambdaKotlin 内联函数与 Java 的互操作性强大的类型推断协程支持lazy 委托object 单例模式区间表达式现代的开发工具支持 本文首发地址 https://h89.cn/archives/301.html 最新更新地址 https://gite…

2024-07-27 Unity Excel —— 使用 EPPlus 插件读取 Excel 文件

文章目录 1 前言2 项目地址3 使用方法3.1 写入 Excel3.2 读取 Excel3.3 读写 csv 文件 4 ExcelSheet 代码 1 前言 ​ 前几日&#xff0c;一直被如何在 Unity 中读取 Excel 的问题给困扰&#xff0c;网上搜索相关教程相对古老&#xff08;4、5 年以前了&#xff09;。之前想用 …

探索 Electron:如何进行网址收藏并无缝收录网页图片内容?

Electron是一个开源的桌面应用程序开发框架&#xff0c;它允许开发者使用Web技术&#xff08;如 HTML、CSS 和 JavaScript&#xff09;构建跨平台的桌面应用程序&#xff0c;它的出现极大地简化了桌面应用程序的开发流程&#xff0c;让更多的开发者能够利用已有的 Web 开发技能…

嵌入式人工智能(28-基于树莓派4B的语音播报模块-SYN6288)

1、语音播报模块 语音播报在一些嵌入式场景中很常见&#xff0c;广泛应用于游戏篮球机音效语音播报&#xff0c;跑步机语音导航&#xff0c;按摩椅语音操作指引&#xff0c;设备故障提示&#xff0c;设备操作引导语音&#xff0c;车载安全语音警示&#xff0c;公共场所语音提示…

系统移植(七)u-boot移植 ④ trusted版本

文章目录 一、U-boot源码适配&#xff08;一&#xff09;执行make stm32mp15_trusted_defconfig命令进行配置&#xff0c;生成.config文件&#xff08;二&#xff09;执行make menuconfig命令&#xff0c;对u-boot源码进行重新配置1. 对u-boot源码进行配置&#xff0c;移除pmic…

Executable Code Actions Elicit Better LLM Agents

Executable Code Actions Elicit Better LLM Agents Github: https://github.com/xingyaoww/code-act 一、动机 大语言模型展现出很强的推理能力。但是现如今大模型作为Agent的时候&#xff0c;在执行Action时依然还是通过text-based&#xff08;文本模态&#xff09;后者JSO…

Java Web——第一天

Web开发课程安排 Web标准 Web标准也称为网页标准&#xff0c;由一系列的标准组成&#xff0c;大部分由W3C( World Wide Web Consortium&#xff0c;万维网联盟)负责制定 三个组成部分: HTML:负责网页的结构 (页面素和内容) CSS:负责网页的表现 (页面元素的外观、位置等页面…