尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

网络爬虫模拟登录实战:从Selenium到Requests与JS逆向的三种方法

网络爬虫模拟登录实战:从Selenium到Requests与JS逆向的三种方法 1. 从“人人网”说起一个时代的网络爬虫练兵场提起“人人网”很多年轻一代的程序员可能已经感到陌生但对于我们这些经历过Web 2.0时代洗礼的老鸟来说它承载的不仅是青春记忆更是一个绝佳的网络爬虫技术“活化石”和实战演练场。虽然它的辉煌早已褪去但其登录机制却完整地保留了从早期简单明文提交到引入基础验证码再到后来尝试动态加密的典型演进路径。对于一个想系统学习Web自动化与数据采集的开发者而言研究一个已经“静止”但结构完整的系统远比去硬磕那些防护严密、动态变化的大型平台要友好得多风险也低得多。今天我就以“模拟登录人人网”这个具体任务为切口抛开那些泛泛而谈的理论直接上干货。我会带你手把手走通三种主流的实现方法从最直观、最适合新手的Selenium浏览器自动化到效率与复杂度平衡的Requests库配合手动处理Session与Cookie再到追求极致性能和还原度的逆向分析JavaScript加密逻辑。每一种方法都不是简单的代码堆砌我会重点剖析其背后的原理、适用场景以及我在实际爬虫生涯中踩过的那些坑和总结出的技巧。无论你是刚入门想找个靠谱的练手项目还是有一定经验想深化对HTTP协议和前端安全机制的理解这篇文章都能给你带来实实在在的收获。我们的目标不仅仅是“登录成功”更是要弄明白“为什么能成功”以及“哪种方法在什么情况下才是最优选”。2. 战前准备理解目标与备齐弹药在开始写第一行代码之前花点时间做好侦察和准备工作往往能省去后面一大半的调试时间。模拟登录的本质是让我们的程序能够“扮演”一个真实用户通过浏览器与服务器完成身份认证并获取维持登录状态的凭证主要是Cookie。人人网的登录页面虽然已成为历史但其架构非常经典。2.1 目标网站登录流程分析首先我们需要用浏览器的开发者工具F12仔细“阅读”登录页面以存档的静态页面或能找到的镜像为例核心是学习其技术原理。关键看几个点表单结构找到用户名email和密码password的输入框查看它们的name属性。通常表单的action属性指向提交的URLmethod通常是POST。请求分析在Network网络面板中勾选“Preserve log”保留日志然后进行一次手动登录。你会看到点击“登录”按钮后浏览器实际发送出的请求。重点关注这个POST请求。请求URL这就是我们程序需要模拟提交的目标地址。请求头Request Headers特别是Content-Type通常是application/x-www-form-urlencoded、User-Agent用户代理用于标识浏览器和Referer来源页。User-Agent是反爬虫的基础检查点我们必须模拟一个真实的浏览器。请求体Request Body/Payload这是核心。查看提交的数据是什么格式。早期简单系统可能是email你的邮箱password明文密码。但稍复杂的系统会对密码进行前端加密你看到的password字段可能是一长串毫无规律的字符。此外还可能包含一些隐藏字段如csrf_token、lt、execution等这些通常是为了防止跨站请求伪造CSRF或维持会话状态需要从登录页面的HTML源码中提前提取。响应分析登录请求的响应是什么成功登录后服务器通常会返回一个302重定向并在响应头里通过Set-Cookie字段下发关键的会话Cookie比如SESSION、登录态token等。我们的程序必须能够捕获并保存这些Cookie后续的请求都要带上它们才能维持登录状态。注意由于人人网已停止主要服务实际操作中你可能无法找到一个真正可用的登录端点。但这不影响我们进行技术原理的演练。你可以使用任何具有类似登录机制的教学网站确保你有合法测试权限或者使用本地搭建的、带有登录功能的测试网站。本文的重点是方法论的传授所有代码逻辑和思路完全通用。2.2 开发环境与工具选择工欲善其事必先利其器。以下是三种方法共用的基础环境以及各自的特需工具。Python 3.7爬虫领域的主流语言生态丰富。建议使用虚拟环境如venv或conda管理项目依赖。核心库requests用于发送HTTP请求的瑞士军刀是方法二和方法三的基础。BeautifulSoup4 (bs4)或lxml用于解析HTML提取表单中的隐藏字段。Selenium浏览器自动化工具用于方法一。它需要一个浏览器驱动如ChromeDriver。浏览器与驱动对于Selenium你需要安装一个浏览器推荐Chrome或Firefox和对应的WebDriver。确保驱动版本与浏览器版本匹配并将其路径加入系统环境变量或在代码中指定。调试工具浏览器开发者工具DevTools如前所述是分析请求的利器。Fiddler / Charles / Wireshark网络抓包工具可以更细致地查看所有网络流量对于分析复杂的加密流程有帮助。PyCharm / VSCode带调试功能的IDE便于设置断点、查看变量。准备好这些我们就可以正式进入三种方法的实战环节了。每种方法我都会从原理讲起然后给出详细的代码步骤并穿插我个人的经验与避坑指南。3. 方法一Selenium浏览器自动化——所见即所得的新手之选这是最直观、最接近人工操作的方法。它的核心思想是用程序控制一个真实的浏览器像人一样去点击、输入、提交。这种方法几乎能绕过所有前端加密和复杂的JavaScript逻辑因为浏览器本身会执行这些JS代码并完成渲染。3.1 为什么选择Selenium它的优势与代价优势绕过前端加密密码加密、动态Token生成等JavaScript逻辑都由浏览器自动执行我们只需关心最终在输入框里填什么点哪个按钮。处理复杂交互对于需要拖动滑块、点击验证码等图形交互的登录Selenium几乎是唯一可行的自动化方案。开发调试简单代码逻辑直白find_element,send_keys,click所见即所得。特别适合爬虫初学者理解Web交互过程。代价性能低下需要启动完整的浏览器内核占用大量内存和CPU速度慢。资源消耗大不适合大规模、高并发的爬取任务。不够“优雅”从爬虫工程角度看它更像是一种“暴力”的集成测试工具而非高效的采集工具。3.2 实战步骤与代码详解假设我们通过分析找到人人网登录页面的关键元素用户名输入框input nameemail typetext密码输入框input namepassword typepassword登录按钮button typesubmit idlogin_button登录/buttonfrom 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 import time def login_with_selenium(username, password, login_url): 使用Selenium模拟登录人人网 :param username: 用户名/邮箱 :param password: 密码 :param login_url: 登录页面URL :return: driver对象已登录状态后续可用其进行其他操作 # 1. 初始化浏览器驱动这里以Chrome为例 # 可选配置无头模式不显示浏览器界面提升性能且适合服务器环境 options webdriver.ChromeOptions() # options.add_argument(--headless) # 开启无头模式 # options.add_argument(--disable-gpu) # options.add_argument(--no-sandbox) # Linux服务器有时需要 # 非常重要设置一个合理的User-Agent options.add_argument(user-agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36) driver webdriver.Chrome(optionsoptions) # 确保chromedriver在PATH中 try: # 2. 访问登录页面 driver.get(login_url) # 显式等待确保页面元素加载完成比time.sleep更智能 wait WebDriverWait(driver, 10) # 3. 定位并填写用户名 # 使用CSS选择器、XPath或By.NAME等方式定位元素 email_input wait.until( EC.presence_of_element_located((By.NAME, email)) ) email_input.clear() # 清空可能存在的默认值 email_input.send_keys(username) # 输入用户名 print(已输入用户名) # 4. 定位并填写密码 password_input driver.find_element(By.NAME, password) password_input.send_keys(password) print(已输入密码) # 5. 定位并点击登录按钮 login_button driver.find_element(By.ID, login_button) login_button.click() print(已点击登录按钮) # 6. 等待登录完成可根据跳转后的URL或某个登录后特有的元素来判断 # 例如等待用户主页的某个元素出现 # wait.until(EC.url_contains(home)) # 等待URL包含home # 或者 # wait.until(EC.presence_of_element_located((By.CLASS_NAME, user-name))) time.sleep(3) # 简单等待实际项目应用上面更智能的等待方式 print(登录过程完成或已尝试) # 7. 验证登录是否成功简单示例 current_url driver.current_url if login not in current_url: # 如果当前URL不再包含login可能登录成功 print(f可能登录成功当前页面: {current_url}) # 可以尝试获取登录后才能看到的信息如昵称 # try: # nickname driver.find_element(By.CSS_SELECTOR, .nickname).text # print(f登录用户: {nickname}) # except: # print(未找到用户信息登录状态可能异常) else: print(可能仍在登录页登录失败。请检查账号密码或页面结构。) # 可以在这里截图便于调试 # driver.save_screenshot(login_failed.png) # 返回driver对象后续所有操作都基于这个已登录的会话 return driver except Exception as e: print(f登录过程中发生错误: {e}) driver.save_screenshot(error.png) # 出错时截图 driver.quit() return None # 使用示例 if __name__ __main__: # 注意以下URL和账号密码仅为示例格式实际需替换 test_url https://example-renren-login.com # 假设的登录页 my_username your_emailexample.com my_password your_password logged_in_driver login_with_selenium(my_username, my_password, test_url) if logged_in_driver: # 登录成功后可以用这个driver去访问需要登录的页面 # logged_in_driver.get(https://example-renren-login.com/home) # ... 执行其他数据采集操作 ... # 最后记得关闭浏览器 time.sleep(5) # 演示停留 logged_in_driver.quit()3.3 Selenium实战中的“坑”与技巧元素定位失败这是最常见的问题。页面加载速度、动态JS生成元素、iframe嵌套等都可能导致find_element失败。技巧优先使用WebDriverWait配合expected_conditions进行显式等待绝对避免无脑time.sleep。尝试多种定位方式ID Name CSS Selector XPath。对于动态加载的内容可能需要等待特定条件如元素可点击、元素存在等。排查在关键步骤后使用driver.save_screenshot(‘step.png’)截图或者用driver.page_source打印当前HTML源码检查元素是否真的存在。无头模式Headless下的差异有些网站在检测到无头浏览器时行为会不同甚至直接屏蔽。技巧可以添加一些参数来让浏览器更像真人操作options.add_argument(--disable-blink-featuresAutomationControlled) options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False)终极方案如果无头模式被识别可以暂时使用有头模式进行开发和调试。Cookie与Session管理Selenium的driver对象自动管理Cookie。登录成功后所有Cookie都保存在driver中。如果你想将这次登录的会话状态Cookie保存下来供其他非Selenium的请求如requests使用可以这样做cookies driver.get_cookies() # cookies是一个字典列表可以转换为requests库可用的格式 session requests.Session() for cookie in cookies: session.cookies.set(cookie[‘name’], cookie[‘value’]) # 现在session就携带了登录态小结Selenium是入门和解决复杂前端交互的利器但性能是硬伤。当你需要快速验证登录逻辑、处理图形验证码或者目标网站前端极其复杂时它是首选。但对于需要高效、稳定、大规模运行的爬虫生产环境我们需要更轻量级的方法。4. 方法二Requests Session —— 轻量级HTTP客户端的艺术这是爬虫工程师最常用、最经典的方法。它直接模拟浏览器发送HTTP请求不经过浏览器渲染因此效率极高。核心在于正确地构建请求包括URL、请求头、请求体并妥善管理服务器返回的会话Session。4.1 核心原理会话Session与Cookie的自动管理requests.Session()对象是这里的灵魂。它会在一次会话中自动保存服务器通过Set-Cookie下发的Cookie并在后续的请求中自动携带这些Cookie。这完美模拟了浏览器标签页的行为。我们的任务就是用代码构造出和浏览器一模一样的登录POST请求。4.2 实战步骤分解我们假设一个稍微复杂但很常见的场景登录页面有一个随机的csrf_token或叫lt、execution等需要随表单一起提交。步骤1获取登录页面提取隐藏字段import requests from bs4 import BeautifulSoup def get_login_page(session, login_url): 获取登录页面并解析出必要的隐藏字段如csrf_token。 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } resp session.get(login_url, headersheaders) resp.raise_for_status() # 如果请求失败则抛出异常 soup BeautifulSoup(resp.text, html.parser) # 假设csrf_token在一个name为‘csrf_token’的隐藏input标签里 csrf_token_input soup.find(input, {name: csrf_token}) # 或者有时叫 ‘lt’ lt_input soup.find(input, {name: lt}) tokens {} if csrf_token_input and csrf_token_input.get(value): tokens[csrf_token] csrf_token_input[value] if lt_input and lt_input.get(value): tokens[lt] lt_input[value] # 同时我们还需要获取表单提交的action地址如果和login_url不同 login_form soup.find(form, idloginForm) # 根据实际表单ID或特征查找 if login_form and login_form.get(action): # 处理相对路径拼接成完整URL from urllib.parse import urljoin submit_url urljoin(login_url, login_form[action]) else: submit_url login_url # 默认就是当前页 return tokens, submit_url步骤2构建登录请求数据并提交def submit_login(session, submit_url, tokens, username, password): 构建POST数据并提交登录请求。 # 构建请求数据。注意字段名必须和表单一致。 login_data { email: username, password: password, # 注意这里假设密码是明文。如果是前端加密请看方法三。 csrf_token: tokens.get(csrf_token, ), lt: tokens.get(lt, ), # 可能还有其他固定字段如 ‘execution’, ‘_eventId’ 等需要从页面源码中提取 _eventId: submit, submit: 登录 } # 登录请求的Headers通常需要Referer并且Content-Type是表单格式 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: submit_url, # 来源页通常是登录页本身 Content-Type: application/x-www-form-urlencoded } # 关键使用session.postsession会自动管理Cookie resp session.post(submit_url, datalogin_data, headersheaders, allow_redirectsFalse) # 先禁止自动重定向 # 检查响应 print(f登录请求状态码: {resp.status_code}) # 登录成功通常返回302重定向并且会在响应头Location里指示跳转地址 if resp.status_code 302: redirect_url resp.headers.get(Location) print(f登录成功重定向至: {redirect_url}) # 此时登录成功的Cookie已经被自动保存在session.cookies里了 return True, redirect_url else: # 登录失败可能返回200并停留在登录页或者返回其他错误码 print(登录可能失败。响应内容前500字符:, resp.text[:500]) return False, None步骤3验证登录状态并访问受保护页面def test_logged_in(session, home_url): 尝试访问一个需要登录才能查看的页面如个人主页验证session是否有效。 resp session.get(home_url) # 验证方式1检查返回的HTML中是否包含登录后才有的特征字符串如用户名 if 我的主页 in resp.text or logout in resp.text.lower(): # 根据实际页面调整 print(验证成功已处于登录状态。) return True # 验证方式2检查URL如果被重定向回登录页则失败 elif login in resp.url: print(验证失败被重定向至登录页。) return False else: print(验证状态不确定请手动检查响应内容。) return False # 主函数整合 def login_with_requests(username, password, login_url, home_url): 使用Requests Session 完成完整登录流程。 # 创建一个会话对象它将为我们自动保存Cookie session requests.Session() # 步骤1获取登录页和Token print(步骤1获取登录页面及Token...) try: tokens, submit_url get_login_page(session, login_url) print(f获取到的Token: {tokens}) print(f表单提交地址: {submit_url}) except Exception as e: print(f获取登录页失败: {e}) return None # 步骤2提交登录信息 print(\n步骤2提交登录信息...) success, redirect_url submit_login(session, submit_url, tokens, username, password) if not success: print(登录提交失败。) return None # 步骤3如果重定向了可以跟随重定向session会自动处理但之前我们设置了allow_redirectsFalse # 这里我们手动跟随一次重定向或者直接用新的session去访问 if redirect_url: # 用同一个session去访问重定向地址会自动携带Cookie session.get(redirect_url) # 步骤4验证登录状态 print(\n步骤4验证登录状态...) is_logged_in test_logged_in(session, home_url) if is_logged_in: print(恭喜使用Requests登录成功。) # 返回这个携带了登录态Cookie的session对象用于后续所有请求 return session else: print(登录状态验证未通过。) return None # 使用示例 if __name__ __main__: # 假设的URL和账号 login_page_url https://example-renren-login.com/login user_home_url https://example-renren-login.com/home my_username your_emailexample.com my_password your_password logged_in_session login_with_requests(my_username, my_password, login_page_url, user_home_url) if logged_in_session: # 现在可以用这个session去爬取需要登录的数据了 # 例如获取好友列表 # friends_page logged_in_session.get(https://example-renren-login.com/friends) # ... 解析 friends_page.text ... print(Session已就绪可进行后续数据采集。) # 打印一下当前的Cookies看看 print(f当前会话Cookies: {logged_in_session.cookies.get_dict()})4.3 Requests方法的关键细节与避坑指南请求头Headers的模仿这是反爬虫的第一道防线。除了User-Agent和Referer有时还需要Origin、Accept-Language、Accept-Encoding等。最稳妥的办法是从浏览器开发者工具里把登录POST请求的所有Headers除了Content-Length等动态生成的都复制下来用在你的session.post()请求中。处理重定向Redirects登录成功后返回302是标准做法。requests默认是自动处理重定向的allow_redirectsTrue。但我建议在登录请求时先关闭自动重定向allow_redirectsFalse因为你可以检查状态码是否为302来快速判断登录是否被服务器接受。你可以从响应头中获取重定向地址这个地址有时包含了重要的信息。你可以控制重定向的过程避免一些意外的跳转。获取到重定向URL后再用session.get()去访问这样Cookie管理依然是连贯的。Session的生命周期一个session对象代表一次“会话”。只要你不关闭程序或不显式地清除cookiessession.cookies.clear()登录状态就会一直保持。这对于需要连续访问多个页面的爬虫任务非常方便。验证码处理如果登录有验证码此方法就遇到了瓶颈。你需要额外集成验证码识别服务如OCR API或机器学习模型来识别图片验证码或者考虑切换到Selenium进行人工干预。对于简单的数字字母验证码可以尝试pytesseract等OCR库但识别率在复杂背景下往往不高。小结Requests Session是效率与复杂度之间的完美平衡点适用于绝大多数没有复杂前端加密或图形验证码的网站。它要求开发者对HTTP协议有基本的理解并能熟练使用开发者工具进行分析。这是爬虫工程师的必备技能。5. 方法三逆向JS加密——直面前端安全机制的挑战当网站对密码进行了前端JavaScript加密时你直接发送明文密码是无效的。你会发现方法二中提交的password字段其值不是你输入的123456而是一串像a1b2c3d4e5...的密文。这时我们就需要深入前端代码找到加密算法并在Python中复现它。这是三种方法中技术难度最高但也是最彻底、性能最好的方法。5.1 识别加密从Network面板开始在浏览器的Network面板中找到登录的POST请求查看Form Data部分。如果password的值是一长串乱码基本可以确定是前端加密了。5.2 定位加密代码开发者工具的Sources面板这是最关键也最需要耐心的一步。我们需要找到负责加密的JavaScript函数。全局搜索在Sources面板中按CtrlShiftF(Windows) 或CmdOptF(Mac) 打开全局搜索。搜索关键词可以是password、encrypt、md5、sha1、RSA、encode等。关注那些在输入框事件如onblur,onchange或表单提交事件onsubmit中被调用的函数。事件监听器断点在Elements面板找到密码输入框右键选择“Break on” - “attribute modifications” 或 “subtree modifications”。然后在密码框输入内容程序会断点在修改密码值的JS代码处。XHR/Fetch断点在Sources面板的XHR/Fetch Breakpoints里添加一个包含登录接口URL部分的断点。当登录请求发起时代码会暂停此时调用栈Call Stack可以帮你回溯到发起请求和加密数据的函数。5.3 分析与复现加密逻辑假设我们经过一番搜索在某个JS文件里找到了类似如下的代码function encryptPassword(pwd) { // 假设这里是一个简单的Base64编码或者用了某个公共库如CryptoJS var key CryptoJS.enc.Utf8.parse(一个固定的密钥); var srcs CryptoJS.enc.Utf8.parse(pwd); var encrypted CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7}); return encrypted.toString(); } // 或者在表单提交时 $(#loginForm).submit(function(){ var rawPwd $(#password).val(); $(#password).val(encryptPassword(rawPwd)); // 将明文替换为密文 return true; });情况一使用标准加密库如CryptoJS如果网站使用了常见的开源加密库如CryptoJS、sjcl等那么恭喜你在Python中有对应的库可以完美复现。例如对于上面的AES加密我们可以用pycryptodome库来实现。from Crypto.Cipher import AES from Crypto.Util.Padding import pad import base64 def encrypt_password_js_style(password): 模拟JavaScript中的CryptoJS.AES.encrypt (ECB模式, Pkcs7填充) key 一个固定的密钥.encode(utf-8) # 密钥需要和JS里一致 # 注意CryptoJS默认使用Utf8编码PKCS7填充 cipher AES.new(key, AES.MODE_ECB) # 对明文进行PKCS7填充 padded_data pad(password.encode(utf-8), AES.block_size) encrypted_bytes cipher.encrypt(padded_data) # CryptoJS默认输出的是Base64格式的字符串 encrypted_b64 base64.b64encode(encrypted_bytes).decode(utf-8) return encrypted_b64 # 在登录数据中使用 login_data[password] encrypt_password_js_style(my_password)情况二自定义或混淆的加密函数如果加密函数是网站自己写的或者被严重混淆了事情就麻烦一些。你需要仔细阅读JS代码理解其每一步操作可能是多次MD5、拼接字符串、反转、自定义编码等。在浏览器控制台Console里测试将找到的加密函数复制到Console传入测试密码看输出是否和Network里捕获的密文一致。这是验证你找到的函数是否正确的最直接方法。在Python中逐行翻译将JS的每一步逻辑用Python实现。常用的Python库有hashlib用于MD5, SHA1等、base64、json等。例如如果JS里是md5(md5(password) ‘salt’)import hashlib def custom_encrypt(password, salt固定盐值): first_md5 hashlib.md5(password.encode()).hexdigest() combined first_md5 salt final_md5 hashlib.md5(combined.encode()).hexdigest() return final_md5 login_data[password] custom_encrypt(my_password)情况三非对称加密如RSA有些网站会用RSA公钥对密码进行加密。你需要在页面HTML或JS中找到公钥通常是一个很长的字符串以-----BEGIN PUBLIC KEY-----开头。然后在Python中使用rsa或Crypto库进行加密。import rsa import base64 def rsa_encrypt(password, public_key_str): # 加载公钥 pub_key rsa.PublicKey.load_pkcs1(public_key_str.encode()) # 加密RSA加密有长度限制通常只加密密码或一个随机密钥 encrypted_bytes rsa.encrypt(password.encode(), pub_key) # 通常结果会被Base64编码后传输 return base64.b64encode(encrypted_bytes).decode() # 假设从页面中提取到了public_key_str # login_data[password] rsa_encrypt(my_password, public_key_str)5.4 逆向工程的“道”与“术”保持耐心逆向JS是最耗时的尤其是面对混淆代码时。善用浏览器的“美化Pretty print”功能Sources面板左下角的{}图标让压缩的代码变得可读。动态调试在关键的加密函数入口设置断点单步执行F10观察每一步的变量值这是理解逻辑的最快方式。借助工具对于简单的混淆可以尝试在线JS反混淆工具。对于复杂的可能需要一定的JS功底。验证再验证在Python中实现加密函数后一定要用多组测试数据包括你真实的测试账号密码与浏览器控制台的结果进行比对确保100%一致。一个字符的差异都会导致登录失败。留意环境变量有些加密可能会用到浏览器环境特有的变量如window.navigator.userAgent、时间戳等这些也需要在Python请求中模拟。小结逆向JS加密是爬虫工程师进阶的必经之路。它虽然门槛高但一旦掌握你将能应对绝大多数前端加密的挑战。成功后的成就感也是巨大的因为这代表着你完全理解了客户端与服务器之间的认证流程。结合方法二的Requests Session你将拥有一个高效、稳定、可扩展的登录方案。6. 方法对比与选型策略没有银弹只有最适合至此我们已经详细探讨了三种方法。我们来做一个清晰的对比帮助你在不同场景下做出选择。特性维度Selenium浏览器自动化Requests Session逆向JS加密 Requests核心原理控制真实浏览器执行所有JS直接模拟HTTP请求管理Cookie破解前端加密再模拟HTTP请求技术难度低易于上手中需理解HTTP高需JS逆向能力开发效率高代码直白中需分析请求低逆向耗时运行效率极低资源占用大高轻量快速高轻量快速抗反爬能力强行为与真人无异中依赖请求头模仿中依赖加密还原处理验证码容易可人工/自动化处理困难需额外集成识别困难需额外集成识别适用场景1. 初学者学习2. 有复杂JS交互/验证码3. 快速原型验证1. 无前端加密的绝大多数网站2. 需要高性能爬取3. 生产环境主流选择1. 存在前端加密的网站2. 对性能和稳定性要求高3. 作为Requests方法的增强我的个人经验与选型建议对于人人网这类“老式”但结构清晰的网站我推荐直接从方法二RequestsSession开始尝试。大概率它的登录就是简单的表单提交顶多加个CSRF Token。这是最快捷、最专业的方式。如果方法二失败Network里看到密码被加密了那就进入方法三逆向JS的挑战。这是提升个人技术深度的好机会。Selenium方法一是我在以下情况的首选1) 时间紧迫需要快速拿到数据不在乎效率2) 目标网站有滑动验证码等图形交互3) 我只是想写个一次性脚本或者给非技术人员演示流程。在实际大型爬虫项目中混合使用是常态。例如用Selenium处理登录解决验证码登录成功后提取Cookie再注入到Requests的Session中后续的爬取全部用高效的Requests进行。7. 登录之后的江湖会话维持与反爬虫对抗成功登录只是万里长征第一步。维持登录状态会话和应对网站的反爬虫机制才是长期的挑战。7.1 会话Session的维持与失效处理Cookie的生命周期服务器下发的Cookie通常有有效期Expires或Max-Age。你的爬虫程序需要运行足够长的时间时就要考虑Cookie过期的问题。心跳与保活有些网站的登录态需要定期活动来维持。你的爬虫在长时间空闲后可能发现Session失效了。解决方案是定时例如每隔30分钟用已登录的Session去访问一个轻量级的页面如个人中心模拟用户活动。失效重登在发起任何请求后检查响应内容或状态码。如果发现被重定向到登录页或者返回了“未登录”的JSON信息说明会话已失效。此时你的程序应该能自动触发重新登录的流程并更新Session中的Cookie。这需要将登录逻辑封装成一个可重用的函数或类方法。7.2 应对常见的反爬虫策略登录后的爬取同样会触发反爬虫。请求头Headers始终携带完整的、像浏览器的Headers。User-Agent可以准备一个池子轮流使用。请求频率与间隔这是最容易被封IP的原因。一定要在请求间添加随机延时如time.sleep(random.uniform(1, 3))避免规律性的高频访问。对于重要网站频率要模拟真人非常慢。IP代理池对于大规模爬取使用代理IP是必须的。免费的代理不稳定商业代理API是更靠谱的选择。确保你的请求能通过代理IP发送。行为模式过于规律的行为如固定间隔访问、永远从A页面到B页面容易被识别。可以引入随机性比如在访问页面序列中随机跳转模拟浏览行为。验证码再现即使登录时没有验证码在后续高频爬取时也可能触发。需要有备用的验证码处理方案如打码平台、模型识别、或人工介入。模拟登录人人网的三种方法本质上是一个由浅入深、从“黑盒”到“白盒”的爬虫技术学习路径。从Selenium的自动化操作到Requests对HTTP协议的精确模拟再到逆向JS对前端逻辑的深度理解每一步都对应着爬虫工程师能力图谱上的一块重要拼图。掌握它们你就能从容应对大多数网站的认证门槛。记住技术是手段合规使用和尊重robots.txt是前提。希望这篇长文能成为你爬虫路上的一块坚实垫脚石。
返回列表