登录后爬取网页遇JS加载问题:requests_html与BeautifulSoup报错求解
问题分析与解决:JS检测、SSL错误及Selenium源码异常问题
场景复现
- 仅使用
BeautifulSoup+requests爬取登录后的页面,页面返回提示:Please enable JavaScript to continue using this application. - 改用
requests_html执行以下代码,仍出现相同JS提示,或抛出错误pyppeteer.errors.PageError: net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
from requests_html import HTMLSession session = HTMLSession() session.get(url) session.post(loginUrl, data = {"email":"email@gmail.com", "password": "Pass123"}) resp.html.render()
- 转用
selenium可正常加载页面,但将页面源码传入BeautifulSoup后,再次出现JS启用提示
原因分析
静态请求(requests+BeautifulSoup)的限制
目标网站启用了JS检测机制,会验证请求客户端是否具备JS执行能力。requests仅发送HTTP请求,不会渲染JS,服务器检测到无JS执行环境后返回拦截页面。requests_html的核心问题
- 会话状态未正确传递:代码中未将
post请求的响应赋值给resp,后续resp.html.render()操作的是初始get请求的未登录页面,自然仍触发JS检测提示。 - SSL配置不兼容:目标网站的SSL要求特定TLS版本或加密套件,而
requests_html依赖的pyppeteer默认浏览器配置不满足,导致SSL握手失败。
- 会话状态未正确传递:代码中未将
Selenium+BeautifulSoup的异常原因
- 源码抓取时机错误:未等待页面动态内容渲染完成就获取
page_source,导致抓取到的仍是初始拦截页面。 - 反爬检测触发:部分网站会识别Selenium的自动化特征(尤其是headless模式),即使页面看似加载完成,仍返回JS拦截内容。
- 源码抓取时机错误:未等待页面动态内容渲染完成就获取
解决方法
针对requests_html的问题
- 修正会话逻辑,确保操作登录后的页面
将登录请求的响应保存为resp,再执行渲染操作,同时建议先获取登录页的CSRF Token(若网站需要):
from requests_html import HTMLSession from bs4 import BeautifulSoup session = HTMLSession() # 先访问登录页获取必要的CSRF Token(如网站要求) login_page = session.get(loginUrl) csrf_token = login_page.html.find('input[name="csrf_token"]', first=True).attrs['value'] # 发送登录请求并保存响应 resp = session.post(loginUrl, data={ "email": "email@gmail.com", "password": "Pass123", "csrf_token": csrf_token # 若网站需要则添加 }) # 渲染登录后的页面 resp.html.render() # 用BeautifulSoup解析渲染后的源码 soup = BeautifulSoup(resp.html.html, 'html.parser')
- 解决SSL版本/加密套件不匹配问题
在render时指定兼容的浏览器启动参数,匹配目标网站的SSL配置:
# 先通过openssl命令检测网站支持的SSL配置:openssl s_client -connect 目标域名:443 resp.html.render( browser_args=[ '--no-sandbox', '--disable-setuid-sandbox', '--ssl-version-max=TLSv1.2', # 根据网站要求调整版本 '--cipher-suite=ECDHE-ECDSA-AES128-GCM-SHA256' # 替换为网站支持的加密套件 ] )
针对Selenium+BeautifulSoup的问题
- 确保获取渲染完成的页面源码
通过显式等待,等登录后的关键元素加载完成后再抓取源码:
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 bs4 import BeautifulSoup driver = webdriver.Chrome() driver.get(loginUrl) # 执行登录操作 driver.find_element(By.NAME, 'email').send_keys('email@gmail.com') driver.find_element(By.NAME, 'password').send_keys('Pass123') driver.find_element(By.CSS_SELECTOR, 'button[type="submit"]').click() # 等待登录后的核心元素加载(替换为实际页面的元素标识) WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, 'user-dashboard')) ) # 获取渲染完成的源码并解析 page_source = driver.page_source soup = BeautifulSoup(page_source, 'html.parser')
- 绕过Selenium自动化检测
若使用headless模式,添加参数模拟真实浏览器特征:
from selenium.webdriver.chrome.options import Options options = Options() options.add_argument('--headless=new') options.add_argument('--disable-blink-features=AutomationControlled') options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) driver = webdriver.Chrome(options=options)
内容的提问来源于stack exchange,提问作者Fabix
相关产品推荐
相关产品推荐

