别再手写Selenium了!用AI生成动态页面爬虫脚本,Python自动点击/滚动实战指南

发布时间:2026/7/16 12:23:31
别再手写Selenium了!用AI生成动态页面爬虫脚本,Python自动点击/滚动实战指南 摘要面对Vue/React渲染的动态页面还在一行行调试XPath和等待策略本文分享一套“AI辅助生成 人工校验修正”的Selenium爬虫工作流。以某主流招聘网站职位列表页为例演示如何让AI理解页面结构后自动生成包含智能等待、无限滚动、弹窗处理的完整脚本。重点不是“让AI替你写代码”而是如何把AI变成你的“爬虫结对编程搭档”。文末附Prompt模板与避坑清单。一、为什么动态页面爬虫这么痛做过Web爬虫的都懂这个绝望循环打开F12看到完美的HTML结构复制XPath塞进Selenium运行报NoSuchElementException加time.sleep(5)能跑了但慢得像蜗牛换个网络环境又挂了因为页面加载时间变了好不容易稳定了网站前端重构所有定位器全部失效。动态渲染页面的核心难点从来不是“怎么点”而是“什么时候点”。SPA框架的异步渲染、懒加载、虚拟滚动、Toast弹窗遮挡……这些都不是一个静态选择器能解决的。传统做法是靠经验堆显式等待而AI的价值在于它能根据你的自然语言描述快速生成一套“防御性”操作序列你再基于实际DOM做精准校准。这不是“AI一键生成可用代码”的童话而是一种效率翻倍的新工作范式。二、工作流设计人机协作的正确姿势在动手之前先建立一个关键认知AI不懂你目标网站的实时DOM它只懂通用模式。所以我们的流程必须是闭环的否是人工: 分析页面结构截图/F12/DOM片段Prompt工程:结构化描述约束条件AI生成:Selenium脚本初稿人工: 本地运行断点调试通过?反馈错误信息给AI修正脚本固化异常处理增强三个原则喂上下文不喂URLAI无法访问网页你必须提供DOM片段、CSS类名规律、交互行为描述要策略不要硬编码要求AI生成“等待元素可点击”而非“sleep 3秒”迭代修正不求一步到位第一轮生成的是骨架第二轮修边界case第三轮加健壮性。三、实战案例爬取动态加载的职位列表我们选择一个典型的SPA招聘站点职位搜索页作为靶标文中隐去具体域名方法通用。该页面特征React渲染首屏仅加载20条滚动到底部触发AJAX加载更多职位卡片有“展开详情”按钮点击后弹出Modal偶发Cookie同意弹窗遮挡操作列表容器使用虚拟滚动DOM节点会复用。3.1 第一步人工采集页面指纹打开F12记录以下关键信息这是给AI的“弹药”观察项记录内容用途列表容器div.job-list-container滚动监听目标单条职位article.job-card[data-job-id]数据提取锚点展开按钮button.expand-btn(卡片内)触发ModalModal内容div.modal-overlay .job-detail详情提取关闭按钮button.modal-close[aria-label关闭]弹窗清理Cookie弹窗div.cookie-banner button.accept前置拦截加载指示器div.loading-spinner(消失加载完)滚动等待信号无更多数据p.no-more-data(出现终止)终止条件技巧在F12 Console里执行document.querySelector(xxx)验证选择器是否唯一有效再喂给AI。别把猜测当事实。3.2 第二步构造结构化Prompt以下是经过多轮迭代验证的高效Prompt模板可直接复用你是一个资深Python自动化测试工程师。请为我生成一个Selenium WebDriver脚本用于爬取一个React SPA招聘网站的职位列表。 ## 页面结构已验证 - 列表容器: div.job-list-container - 职位卡片: article.job-card[data-job-id] - 展开详情按钮: button.expand-btn (在每个卡片内部) - 详情Modal: div.modal-overlay .job-detail - Modal关闭按钮: button.modal-close[aria-label关闭] - Cookie同意弹窗: div.cookie-banner button.accept (可能出现) - 加载中指示器: div.loading-spinner - 无更多数据标记: p.no-more-data ## 功能需求 1. 启动浏览器访问指定URL 2. 检测并处理Cookie弹窗如果出现则点击接受超时3秒忽略 3. 无限滚动加载每次滚动到底部等待loading-spinner消失或no-more-data出现 4. 对每个职位卡片提取data-job-id、标题、公司、薪资点击expand-btn获取详情文本关闭Modal 5. 收集所有数据到列表最终打印JSON ## 技术约束必须遵守 - 使用selenium 4.x webdriver-manager - 禁止使用time.sleep()作为等待策略 - 所有等待必须用WebDriverWait expected_conditions - 滚动使用JavaScript execute_script不用ActionChains - Modal操作前后加try-except失败时记录日志跳过 - 添加合理的隐式等待和页面加载超时 - 代码注释用中文解释每段等待策略的设计意图 - 返回完整可运行的单文件脚本为什么这样写有效角色设定限定“自动化测试工程师”而非“爬虫开发者”AI会更注重稳定性而非激进抓取已验证标签明确告知选择器是经过人工确认的避免AI编造负面约束“禁止sleep”比“请用显式等待”更有强制力容错要求提前声明异常处理粒度减少后期返工。3.3 第三步AI生成脚本的核心逻辑解析AI通常会生成如下结构的代码展示关键片段与设计思路fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasECfromselenium.common.exceptionsimportTimeoutException,NoSuchElementExceptionimportjsonimportlogging logging.basicConfig(levellogging.INFO,format%(asctime)s [%(levelname)s] %(message)s)loggerlogging.getLogger(__name__)classJobScraper:def__init__(self,url):self.urlurl self.driverwebdriver.Chrome()self.driver.set_page_load_timeout(30)self.waitWebDriverWait(self.driver,10)self.jobs[]def_dismiss_cookie_banner(self): Cookie弹窗是可选的前置障碍。 用短超时探测存在则点击不存在则静默跳过。 不使用全局隐式等待避免影响后续正常元素的等待节奏。 try:banner_waitWebDriverWait(self.driver,3)accept_btnbanner_wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,div.cookie-banner button.accept)))accept_btn.click()logger.info(✓ Cookie弹窗已处理)exceptTimeoutException:logger.debug(未检测到Cookie弹窗继续执行)def_scroll_to_load_all(self): 无限滚动核心逻辑。 终止条件双重保险要么出现无更多标记要么连续两次滚动后高度不变。 等待loading-spinner消失作为单次加载完成的信号而非固定延时。 last_height0stall_count0whileTrue:# 检查终止标志ifself.driver.find_elements(By.CSS_SELECTOR,p.no-more-data):logger.info(✓ 已到达列表底部检测到终止标记)break# 执行滚动self.driver.execute_script(arguments[0].scrollTop arguments[0].scrollHeight;,self.driver.find_element(By.CSS_SELECTOR,div.job-list-container))# 等待加载完成spinner消失 OR 超时兜底try:self.wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR,div.loading-spinner)))exceptTimeoutException:logger.warning(加载指示器等待超时尝试继续...)# 防死循环高度停滞检测new_heightself.driver.execute_script(return arguments[0].scrollHeight;,self.driver.find_element(By.CSS_SELECTOR,div.job-list-container))ifnew_heightlast_height:stall_count1ifstall_count2:logger.info(✓ 滚动高度停滞判定加载完毕)breakelse:stall_count0last_heightnew_heightdef_extract_job_detail(self,card): 单条职位的数据提取 Modal交互。 Modal操作包裹在独立try-except中 失败不影响外层循环仅记录警告。 job{id:card.get_attribute(data-job-id),title:card.find_element(By.CSS_SELECTOR,.job-title).text,company:card.find_element(By.CSS_SELECTOR,.company-name).text,salary:card.find_element(By.CSS_SELECTOR,.salary-tag).text,}try:expand_btncard.find_element(By.CSS_SELECTOR,button.expand-btn)expand_btn.click()detail_elself.wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR,div.modal-overlay .job-detail)))job[detail]detail_el.text close_btnself.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,button.modal-close[aria-label关闭])))close_btn.click()# 等待Modal完全消失再继续下一条避免DOM冲突self.wait.until(EC.invisibility_of_element(detail_el))except(TimeoutException,NoSuchElementException)ase:logger.warning(f职位{job[id]}详情提取失败:{e})job[detail]None# 尝试兜底关闭可能残留的Modaltry:self.driver.find_element(By.CSS_SELECTOR,button.modal-close[aria-label关闭]).click()exceptException:passreturnjobdefrun(self):try:self.driver.get(self.url)self._dismiss_cookie_banner()self._scroll_to_load_all()cardsself.driver.find_elements(By.CSS_SELECTOR,article.job-card[data-job-id])logger.info(f共发现{len(cards)}个职位卡片)fori,cardinenumerate(cards):logger.info(f正在处理第{i1}/{len(cards)}条...)jobself._extract_job_detail(card)self.jobs.append(job)print(json.dumps(self.jobs,ensure_asciiFalse,indent2))returnself.jobsfinally:self.driver.quit()3.4 第四步人工校验与修正要点AI生成的脚本通常能达到80%可用度剩下20%需要你根据真实环境修补AI常见缺陷修正方法原因滚动目标选错容器F12确认实际可滚动元素可能是父级wrapperAI只能猜不能看Modal关闭后DOM未刷新增加invisibility_of_element等待AI常忽略过渡动画耗时虚拟滚动导致卡片复用改用data-job-id去重而非索引这是SPA特有陷阱异常处理粒度过粗拆分try块区分“找不到”和“点了没反应”便于定位故障点缺少浏览器参数补充--disable-blink-featuresAutomationControlled反检测基础配置特别强调虚拟滚动问题很多现代列表组件如react-virtualized只渲染可视区DOM。如果你滚动后再回头找之前的卡片它们可能已被销毁。解决方案是在滚动过程中边滚边提取而非滚完再统一提取。这需要修改AI生成的流程顺序是人机协作中典型的“AI给骨架、人改血肉”场景。四、进阶让AI帮你写“自愈”逻辑当页面频繁改版时可以让AI生成多策略定位器降级链# Prompt追加要求# 为每个关键元素生成至少3种定位策略按优先级尝试# 全部失败时抛出带有页面截图路径的自定义异常def_safe_find(self,strategies,timeout8): 多策略元素查找降级器。 strategies: [(By.CSS_SELECTOR, xxx), (By.XPATH, //yyy), ...] forby,valueinstrategies:try:elWebDriverWait(self.driver,timeout).until(EC.presence_of_element_located((by,value)))returnelexceptTimeoutException:continue# 全部失败保存现场供分析screenshot_pathfdebug_{int(time.time())}.pngself.driver.save_screenshot(screenshot_path)raiseElementNotFoundError(f所有定位策略均失败:{strategies}\n截图已保存:{screenshot_path})这种模式让脚本在网站小改版时仍能存活大幅降低维护成本。AI擅长生成这种“模式化防御代码”而你负责定义策略优先级和失败后的诊断动作。五、合规与伦理红线技术可行不等于应该做。请务必遵守尊重robots.txt与ToS若网站明确禁止自动化访问立即停止控制频率单次操作间隔≥2秒避免对服务器造成压力不绕过付费墙/登录态仅爬取公开可见内容不采集个人信息职位爬虫只取岗位描述不碰简历、联系方式数据用途受限仅用于个人学习、学术研究或内部分析不得商用或再分发优先使用官方API如果平台提供数据接口永远优先于模拟浏览器。Selenium是最后手段不是首选方案。能用API解决的绝不开浏览器。六、总结AI是放大器不是替代品回顾整个流程AI真正加速的环节是将零散的页面观察转化为结构化代码骨架生成符合最佳实践的等待策略模板补全异常处理、日志、资源清理等“无聊但必要”的代码在你卡住时提供替代实现思路。但它无法替代的是对目标页面真实行为的观察与理解对业务需求的判断哪些数据值得爬、爬到什么程度够用对法律与伦理边界的把握对运行时异常的根因分析。把AI当作一个经验丰富但不了解你项目的同事你提供详尽的需求文档和现场照片它给出专业建议和代码草稿你审核、测试、调整最终交付可靠的产品。这才是“AI爬虫”在2026年应有的成熟姿态。下次遇到棘手的动态页面别再对着空白编辑器发呆。花10分钟整理页面指纹写一段结构化Prompt让AI先跑起来——然后你来把它变好。免责声明本文所述技术仅用于编程学习与自动化测试研究。使用者应自行评估目标网站的访问政策与法律法规确保行为合规。因不当使用引发的任何法律纠纷或服务封禁责任由使用者承担。文中示例代码已做脱敏与泛化处理不构成对任何特定网站的爬取指导。