ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Python Selenium自动化实战:模拟真人行为的浏览器交互与防检测策略

Python Selenium自动化实战:模拟真人行为的浏览器交互与防检测策略 最近在整理个人项目时发现一个挺有意思的需求想给自己在某个“冷圈”指小众、热度不高的同人创作圈子里画的画增加一些真实的互动氛围但又特别反感那些无脑刷数据的“点赞机器人”。这种机器人不仅破坏了社区生态让真实的反馈变得毫无意义也违背了创作者分享的初衷。于是我决定动手实现一个更“聪明”、更“干净”的自动化互动工具。它不是一个简单的刷赞脚本而是一个能够模拟真人行为、关注内容本身、并完全可控的辅助程序。本文将完整分享从思路设计、技术选型到代码实现的全部过程涵盖环境搭建、核心逻辑、防封策略以及最佳实践。无论你是想学习 Python 自动化、Selenium 操控浏览器还是想了解如何优雅地处理网络请求和模拟用户行为这篇文章都能提供一套可直接复用的实战方案。1. 项目背景与核心思路1.1 什么是“冷圈”与“点赞机器人”在开始技术细节之前有必要先明确两个概念冷圈通常指受众较少、作品更新不频繁、互动量如点赞、评论、转发较低的网络创作圈子。创作者在这里更多是出于热爱而非追求流量。点赞机器人指通过程序自动、批量地对大量内容进行点赞或转发、评论的脚本或服务。它们的行为模式固定缺乏对内容的判断主要目的是在短时间内虚假提升数据。我们的目标与后者有本质区别我们不追求数量而是希望为自己或少数认可的作品在合适的时间以更接近真人的方式增加一些有意义的互动同时严格规避机器人检测机制。1.2 核心设计原则为了避免我们的工具变成另一个“机器人”我们制定了以下核心原则内容驱动程序应具备基础的内容识别能力如通过标签、关键词只对符合特定条件的作品进行操作。行为模拟所有操作浏览、点赞必须模拟人类的不确定性包括随机延迟、操作路径变化、甚至“跳过”某些内容。严格限量设置单日、单次运行的最大操作次数远低于平台风控阈值。可配置与白名单所有目标作品或作者应来自可配置的列表白名单而非全网爬取。尊重平台规则明确知晓并遵守目标平台的用户协议本工具仅用于技术学习与个人合法范围内的自动化辅助。1.3 技术方案选型要实现上述原则我们有两种主流技术路径方案A直接调用平台API。最优雅高效的方式但绝大多数社交平台不开放此类自动化互动API且需要复杂的认证OAuth个人开发者难以申请。方案B浏览器自动化。通过程序控制真实浏览器进行操作模拟真人点击。这种方式更通用能绕过一些前端加密逻辑但速度较慢且容易被反爬虫系统检测。考虑到通用性和学习价值本项目选择方案B并使用 Python 的Selenium库作为核心。同时为了增加稳定性和减少被检测的风险我们会配合使用undetected-chromedriver等工具。2. 环境准备与依赖安装2.1 基础环境说明操作系统Windows 10/11, macOS, 或 Linux (Ubuntu 20.04) 均可。本文以 Windows 为例命令在其它系统上可能略有不同。Python 版本 3.8。建议使用 Python 3.8 或 3.9 以获得最佳的库兼容性。包管理工具pip。浏览器Google Chrome 或 Microsoft EdgeChromium 内核。需要确保浏览器已安装。2.2 安装必要的 Python 库我们创建一个新的虚拟环境并安装核心依赖。# 1. 创建并进入项目目录 mkdir cold-circle-helper cd cold-circle-helper # 2. 创建虚拟环境 (可选但推荐) python -m venv venv # Windows 激活 venv\Scripts\activate # Linux/macOS 激活 # source venv/bin/activate # 3. 安装核心库 pip install selenium undetected-chromedriver # 安装用于处理等待和随机数的库 pip install webdriver-managerselenium浏览器自动化的核心库。undetected-chromedriver一个修改版的 ChromeDriver能有效避免被一些网站检测为自动化脚本。webdriver-manager自动管理 ChromeDriver 的下载和版本匹配省去手动下载的麻烦。2.3 项目结构设计在开始编码前先规划一下项目结构这有助于代码管理。cold-circle-helper/ ├── config.yaml # 配置文件存放目标URL、关键词、速率限制等 ├── main.py # 主程序入口 ├── core/ │ ├── __init__.py │ ├── browser_engine.py # 浏览器引擎封装类 │ ├── action_simulator.py # 模拟点击、滚动等行为的类 │ └── content_filter.py # 内容过滤逻辑 ├── utils/ │ ├── __init__.py │ ├── logger.py # 日志记录工具 │ └── delay_utils.py # 随机延迟函数 └── targets.txt # 白名单目标链接或用户ID每行一个3. 核心模块拆解与实现3.1 浏览器引擎封装 (core/browser_engine.py)这是所有操作的基石。我们需要一个稳定、隐蔽的浏览器实例。# core/browser_engine.py import undetected_chromedriver as uc from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time import random from utils.logger import setup_logger logger setup_logger(__name__) class BrowserEngine: def __init__(self, headlessFalse): 初始化浏览器引擎 :param headless: 是否无头模式不显示浏览器界面 self.headless headless self.driver None self.wait None def start(self): 启动浏览器 options Options() # 添加一些常见的反检测参数 options.add_argument(--disable-blink-featuresAutomationControlled) options.add_argument(--disable-gpu) options.add_argument(--no-sandbox) options.add_argument(--disable-dev-shm-usage) # 禁用自动化控制标志 options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) if self.headless: options.add_argument(--headlessnew) # 新版Chrome的无头模式 try: # 使用 undetected_chromedriver 创建驱动 self.driver uc.Chrome(optionsoptions) # 执行CDP命令隐藏webdriver属性 self.driver.execute_script(Object.defineProperty(navigator, webdriver, {get: () undefined})) self.wait WebDriverWait(self.driver, 10) # 显式等待超时10秒 logger.info(浏览器启动成功。) except Exception as e: logger.error(f启动浏览器失败: {e}) raise def get(self, url): 访问指定URL if not self.driver: self.start() logger.info(f正在访问: {url}) self.driver.get(url) # 访问后随机等待一段时间模拟网络延迟和阅读时间 time.sleep(random.uniform(2, 5)) def quit(self): 关闭浏览器 if self.driver: self.driver.quit() logger.info(浏览器已关闭。)3.2 行为模拟器 (core/action_simulator.py)让程序操作看起来像真人。# core/action_simulator.py from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys import time import random from utils.logger import setup_logger from utils.delay_utils import human_delay logger setup_logger(__name__) class ActionSimulator: def __init__(self, driver): self.driver driver self.actions ActionChains(driver) def random_scroll(self, min_pixels300, max_pixels800): 随机滚动页面模拟阅读行为 scroll_pixels random.randint(min_pixels, max_pixels) # 随机决定向上还是向下滚动大部分情况向下 if random.random() 0.8: scroll_pixels -scroll_pixels self.driver.execute_script(fwindow.scrollBy(0, {scroll_pixels});) human_delay(short) # 滚动后停顿 def click_element(self, element, scroll_into_viewTrue): 点击一个元素可先将其滚动到视图中 if scroll_into_view: self.driver.execute_script(arguments[0].scrollIntoView({behavior: smooth, block: center});, element) human_delay(short) # 模拟鼠标移动轨迹 self._move_mouse_to_element(element) human_delay(micro) # 点击前微小延迟 element.click() logger.debug(f点击了元素: {element.text[:50] if element.text else 无文本元素}) human_delay(medium) # 点击后延迟等待页面反应 def _move_mouse_to_element(self, element): 模拟人类不精确的鼠标移动 try: # 获取元素位置 location element.location_once_scrolled_into_view x, y location[x], location[y] # 加入随机偏移 offset_x random.randint(-5, 5) offset_y random.randint(-5, 5) # 使用ActionChains移动鼠标注意某些环境下可能不生效但是一种尝试 self.actions.move_by_offset(x offset_x, y offset_y).perform() time.sleep(random.uniform(0.05, 0.2)) except Exception: # 如果模拟移动失败静默处理直接点击 pass3.3 内容过滤器 (core/content_filter.py)实现“内容驱动”原则的核心决定是否对当前页面进行操作。# core/content_filter.py import re from utils.logger import setup_logger logger setup_logger(__name__) class ContentFilter: def __init__(self, target_keywordsNone, blacklist_keywordsNone): :param target_keywords: 列表作品需包含至少一个关键词 :param blacklist_keywords: 列表作品包含任意一个则跳过 self.target_keywords target_keywords or [] self.blacklist_keywords blacklist_keywords or [] def check_by_page_title(self, driver): 通过页面标题进行初步过滤 title driver.title.lower() logger.debug(f页面标题: {title}) # 黑名单检查 for kw in self.blacklist_keywords: if kw.lower() in title: logger.info(f标题包含黑名单关键词 {kw}跳过。) return False # 如果设置了目标关键词则进行检查 if self.target_keywords: for kw in self.target_keywords: if kw.lower() in title: logger.info(f标题匹配目标关键词 {kw}通过。) return True # 有目标关键词但无一匹配 logger.info(标题未匹配任何目标关键词跳过。) return False # 未设置目标关键词则默认通过仅做黑名单过滤 return True def check_by_page_content(self, driver, content_selectorbody): 通过页面主体内容进行过滤更精确但更慢 try: content_element driver.find_element(By.CSS_SELECTOR, content_selector) full_text content_element.text.lower() except Exception: full_text driver.page_source.lower() # 黑名单检查 for kw in self.blacklist_keywords: if re.search(rf\b{re.escape(kw.lower())}\b, full_text): logger.info(f内容包含黑名单关键词 {kw}跳过。) return False # 目标关键词检查 if self.target_keywords: for kw in self.target_keywords: if re.search(rf\b{re.escape(kw.lower())}\b, full_text): logger.info(f内容匹配目标关键词 {kw}通过。) return True logger.info(内容未匹配任何目标关键词跳过。) return False return True3.4 工具类日志与延迟 (utils/logger.py,utils/delay_utils.py)# utils/logger.py import logging import sys def setup_logger(name, log_filecold_circle_helper.log, levellogging.INFO): 设置日志记录器 formatter logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(message)s) # 文件处理器 file_handler logging.FileHandler(log_file, encodingutf-8) file_handler.setFormatter(formatter) # 控制台处理器 console_handler logging.StreamHandler(sys.stdout) console_handler.setFormatter(formatter) logger logging.getLogger(name) logger.setLevel(level) # 避免重复添加处理器 if not logger.handlers: logger.addHandler(file_handler) logger.addHandler(console_handler) return logger# utils/delay_utils.py import time import random def human_delay(delay_typemedium): 模拟人类操作的不确定性延迟 :param delay_type: micro(0.1-0.5s), short(1-3s), medium(3-8s), long(8-15s), reading(15-30s) delays { micro: (0.1, 0.5), short: (1, 3), medium: (3, 8), long: (8, 15), reading: (15, 30) } min_t, max_t delays.get(delay_type, (2, 5)) sleep_time random.uniform(min_t, max_t) time.sleep(sleep_time) return sleep_time4. 完整实战实现一个“冷圈”互动辅助程序4.1 配置文件 (config.yaml)使用 YAML 文件管理配置更清晰。# config.yaml browser: headless: false # 调试时设为 false实际运行可设为 true behavior: max_actions_per_run: 5 # 单次运行最大操作次数如点赞 action_delay_type: medium # 操作间延迟类型参考 delay_utils scroll_before_action: true # 操作前是否随机滚动 filter: target_keywords: - 冷圈 - 原创 - 手绘 blacklist_keywords: - 广告 - 推广 - 互粉 content_selector: .post-content # 页面内容区域的选择器需根据目标网站调整 targets: # 可以是作品直接链接也可以是用户主页链接程序需要后续解析 - https://example.com/artwork/123 - https://example.com/user/artist_a4.2 主程序逻辑 (main.py)现在我们将所有模块串联起来。# main.py import yaml import random from core.browser_engine import BrowserEngine from core.action_simulator import ActionSimulator from core.content_filter import ContentFilter from utils.logger import setup_logger from utils.delay_utils import human_delay from selenium.webdriver.common.by import By from selenium.common.exceptions import NoSuchElementException, TimeoutException logger setup_logger(__name__) def load_config(config_pathconfig.yaml): 加载配置文件 with open(config_path, r, encodingutf-8) as f: config yaml.safe_load(f) return config def find_and_click_like_button(driver, simulator): 查找并点击点赞按钮需要根据目标网站结构调整 # 这是一个示例选择器不同网站差异巨大 # 常见的选择器模式 button[aria-label*赞], .like-btn, .fav-button, i.like-icon like_selectors [ button[aria-label*赞], button[aria-label*Like], .like-button, .fav-btn, [data-testidlike], svg.like-icon # 有些是SVG图标 ] for selector in like_selectors: try: # 等待元素出现 from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC like_button WebDriverWait(driver, 5).until( EC.presence_of_element_located((By.CSS_SELECTOR, selector)) ) # 检查是否已经点赞过例如按钮被激活 if active in like_button.get_attribute(class) or liked in like_button.get_attribute(class): logger.info(该作品已点赞过跳过。) return False simulator.click_element(like_button) logger.info(点赞成功) return True except (TimeoutException, NoSuchElementException): continue logger.warning(未找到点赞按钮。) return False def process_target_url(driver, simulator, filter, config, url): 处理单个目标URL logger.info(f开始处理: {url}) driver.get(url) human_delay(short) # 1. 内容过滤 if not filter.check_by_page_title(driver): logger.info(根据标题过滤跳过此页面。) return False # 如果需要更精确过滤可以取消下面这行的注释 # if not filter.check_by_page_content(driver, config[filter][content_selector]): # return False # 2. 模拟阅读行为 if config[behavior][scroll_before_action]: for _ in range(random.randint(1, 3)): simulator.random_scroll() human_delay(short) # 3. 执行核心操作例如点赞 action_success find_and_click_like_button(driver, simulator) return action_success def main(): config load_config() logger.info(冷圈互动辅助程序启动。) # 初始化 browser BrowserEngine(headlessconfig[browser][headless]) browser.start() simulator ActionSimulator(browser.driver) content_filter ContentFilter( target_keywordsconfig[filter][target_keywords], blacklist_keywordsconfig[filter][blacklist_keywords] ) # 加载目标列表这里简单处理实际可以从文件或数据库读取 target_urls config[targets] # 也可以从 targets.txt 读取 # with open(targets.txt, r, encodingutf-8) as f: # target_urls [line.strip() for line in f if line.strip()] random.shuffle(target_urls) # 打乱顺序增加随机性 action_count 0 max_actions config[behavior][max_actions_per_run] for url in target_urls: if action_count max_actions: logger.info(f已达到单次运行最大操作次数({max_actions})停止。) break try: success process_target_url(browser.driver, simulator, content_filter, config, url) if success: action_count 1 logger.info(f操作计数: {action_count}/{max_actions}) # 操作成功后等待一段时间再处理下一个 human_delay(config[behavior][action_delay_type]) else: # 即使没操作也稍作延迟避免请求过于频繁 human_delay(short) except Exception as e: logger.error(f处理URL {url} 时发生错误: {e}) human_delay(long) # 出错后等待更久 logger.info(程序运行结束。) browser.quit() if __name__ __main__: main()4.3 运行与验证根据你的目标网站修改config.yaml中的targets列表和filter部分的关键词。最关键的一步修改main.py中的find_and_click_like_button函数。你需要使用浏览器的开发者工具F12检查目标网站的点赞按钮的 HTML 结构找到其唯一或稳定的 CSS 选择器并更新like_selectors列表。这是本程序能否成功运行的核心。在项目根目录下运行python main.py观察浏览器行为如果headless: false和日志输出cold_circle_helper.log确认程序按预期工作。5. 常见问题与排查思路问题现象可能原因排查与解决思路浏览器无法启动或闪退1. Chrome浏览器版本与ChromeDriver不匹配。2. 端口被占用。3. 系统缺少依赖。1. 确保Chrome已更新到最新版使用webdriver-manager可自动匹配。2. 重启电脑或查找占用端口的进程。3. 在Linux系统可能需要安装libnss3、libgconf-2-4等包。找不到页面元素如点赞按钮1. 选择器错误或过时。2. 页面尚未加载完成。3. 元素在iframe内。4. 网站有反爬机制元素被隐藏。1.重点检查使用开发者工具重新确认元素选择器。尝试更通用的选择器或XPath。2. 增加WebDriverWait的等待时间或添加human_delay(medium)。3. 使用driver.switch_to.frame()切换到对应iframe。4. 尝试使用driver.execute_script()直接执行点击的JS代码。程序被识别为机器人操作失败1. 行为模式过于规律。2. 浏览器指纹被检测。3. 请求频率过高。1. 增加human_delay的随机范围加入更多随机滚动、鼠标移动模拟。2. 使用undetected-chromedriver就是为了缓解此问题。可尝试添加更多Chrome选项来修改指纹谨慎操作。3.大幅降低max_actions_per_run并增加操作间隔 (action_delay_type设为long或reading)。日志显示“已点赞过跳过”目标作品之前已被点赞。这是正常逻辑说明过滤功能生效。确保你的find_and_click_like_button函数能正确检测“已点赞”状态。处理到一半程序崩溃网络波动、页面结构突变、意外弹窗。1. 在主循环process_target_url外加强大的try...except。2. 记录崩溃前的URL便于重试。3. 考虑使用signal或atexit来确保浏览器最终被关闭。6. 最佳实践与工程建议遵守平台规则与法律底线首要原则彻底阅读并理解目标网站的robots.txt文件和服务条款。明确禁止自动化的网站请勿使用本程序。最小化影响将max_actions_per_run设置为一个极低的数字例如3-5并且每天只运行1-2次。你的目的是“辅助”不是“轰炸”。用于学习将此项目定位为浏览器自动化、Python编程和反反爬虫技术的学习案例而非生产级工具。增强程序的健壮性与隐蔽性动态选择器不要依赖单一固定的CSS选择器。维护一个选择器列表并让程序依次尝试。定期检查和更新这个列表。代理IP池如果需要对大量不同IP的内容进行操作应考虑使用可靠的代理IP服务并在BrowserEngine中配置。但这对个人“冷圈”项目通常不必要且会增加复杂度。人类行为数据库可以记录你本人手动操作时的延迟数据点击间隔、滚动距离、停留时间用这些真实数据来定义human_delay的参数使模拟更逼真。错误恢复实现重试机制。对于因网络问题失败的操作可以在延迟后重试一次。代码管理与扩展支持多平台可以抽象一个PlatformOperator基类然后为不同的网站如平台A、平台B实现子类。每个子类负责解析其特有的页面结构和操作逻辑。配置化将更多参数放入config.yaml如不同平台的选择器、等待超时时间、是否启用截图调试等。数据持久化使用轻量级数据库如SQLite记录已操作过的作品ID、操作时间、操作结果避免重复操作也便于复盘。任务调度使用系统的cron(Linux/macOS) 或任务计划程序(Windows) 来定时、低频地运行脚本而不是手动执行。伦理思考透明性如果你在公共社区使用此类工具考虑是否需要进行说明。纯粹的“刷数据”对社区有害。目的始终问自己使用这个工具是为了让真正好的作品被看见还是仅仅为了满足虚荣心前者是工具价值的体现后者则可能背离创作初心。通过这个项目你不仅学会了一套具体的Python自动化技术更重要的是理解了在自动化过程中如何平衡效率、隐蔽性与对平台规则的尊重。技术本身是中立的如何使用它取决于你的意图。希望这个“冷圈”小助手能帮你更专注地欣赏和分享那些真正闪光的热爱而不是被数据所困扰。
返回列表