You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python Requests/MechanicalSoup登录factomos网站遇403错误求助

解决factomos登录403错误的排查方案

嘿,我看你在登录factomos平台时碰到了顽固的403问题,不管用requests还是MechanicalSoup都没法成功进入仪表盘。结合你提供的代码,我梳理了几个最可能的原因和对应的修改方案,咱们一步步来排查:

1. 缺少CSRF Token验证

大部分现代网站的登录表单都会要求CSRF Token来防止跨站请求伪造,你的代码里完全没处理这个环节,这很可能是403的核心原因。即使MechanicalSoup会自动处理表单字段,但如果网站的Token字段名比较特殊,或者需要先加载登录页获取会话标识,也会导致提交失败。

修复requests代码:先获取CSRF Token再提交

import requests
from bs4 import BeautifulSoup as bs

url = 'https://factomos.com'
email = 'myemail'
password = 'mypassword'
url_login = 'https://factomos.com/connexion'

# 补充更完整的请求头,模拟真实浏览器行为
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
    'Referer': url_login,  # 告诉服务器请求来自登录页
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
}

with requests.Session() as s:
    # 第一步:先GET登录页面,获取会话Cookie和CSRF Token
    login_page_resp = s.get(url_login, headers=headers)
    soup = bs(login_page_resp.content, 'html.parser')
    
    # 提取CSRF Token(注意:需要根据实际页面的字段名调整,比如可能是_csrf、csrfmiddlewaretoken等)
    csrf_input = soup.find('input', type='hidden')
    if csrf_input and 'name' in csrf_input.attrs:
        csrf_token = csrf_input['value']
        print(f"获取到CSRF Token: {csrf_token}")
    else:
        print("未找到CSRF Token,请检查页面结构")
        exit()
    
    # 构造完整的登录数据,加上CSRF Token
    data_login = {
        'appAction': 'login',  # 建议用浏览器开发者工具确认这个字段名是否正确
        'email': email,
        'password': password,
        csrf_input['name']: csrf_token  # 动态使用页面上的Token字段名
    }
    
    # 第二步:提交登录请求
    dash_resp = s.post(url_login, headers=headers, data=data_login)
    print(f"登录请求状态码: {dash_resp.status_code}")
    
    # 检查响应内容判断是否成功(比如搜索仪表盘关键词)
    if "仪表盘" in dash_resp.text or "dashboard" in dash_resp.text.lower():
        print("登录成功!已进入仪表盘页面")
    else:
        print("登录未成功,响应内容预览:")
        print(dash_resp.text[:500])

2. MechanicalSoup表单选择或字段匹配错误

你的MechanicalSoup代码看起来没问题,但可能存在表单选择不准确,或者字段名和实际页面不匹配的情况。可以加上调试代码确认细节:

修复MechanicalSoup代码:增加调试输出

import mechanicalsoup

browser = mechanicalsoup.StatefulBrowser()
# 打开登录页
resp = browser.open("https://app.factomos.com/connexion")
print(f"登录页加载状态码: {resp.status_code}")

# 先打印页面上所有表单,确认选中的是正确的那个
all_forms = browser.get_current_page().find_all('form')
print(f"页面上找到 {len(all_forms)} 个表单:")
for idx, form in enumerate(all_forms):
    print(f"表单{idx+1} - ID: {form.get('id')}, 提交地址: {form.get('action')}")

# 选中目标表单(如果id不是login-form,需要调整)
browser.select_form('form[id="login-form"]')

# 打印表单内所有字段,确认email和password的name属性
print("\n表单内的输入字段:")
for input_tag in browser.form.find_all('input'):
    print(f"字段名: {input_tag.get('name')}, 类型: {input_tag.get('type')}")

# 填写登录信息
browser["email"] = 'myemail'
browser["password"] = 'mypassword'

# 提交表单
response = browser.submit_selected()
print(f"\n提交状态码: {response.status_code}")

# 检查当前页面是否为仪表盘
current_title = browser.get_current_page().title.string if browser.get_current_page().title else "无标题"
print(f"当前页面标题: {current_title}")
if "dashboard" in current_title.lower() or "仪表盘" in current_title:
    print("登录成功!")
else:
    print("仍停留在登录页,可能是字段错误或验证失败")

3. 其他可能的原因

  • Bot检测机制:如果网站用了Cloudflare或者类似的反爬系统,普通的HTTP请求会被拦截,这时候需要用Selenium或Playwright模拟真实浏览器的交互(比如加载JS、等待页面渲染)。
  • 请求头遗漏关键字段:比如Origin、Content-Type等,你可以通过浏览器开发者工具(F12→网络→登录请求→头信息)复制全量请求头,在代码里完全照搬。
  • 密码或账号问题:虽然你提到更换过数据,但还是建议手动登录一次确认账号密码是否正常,有没有需要二次验证的情况。

排查小技巧

打开浏览器的开发者工具,手动完成一次登录,然后查看网络请求里的POST请求:

  • 对比你代码里的data和浏览器实际发送的表单数据,确保字段名和值完全一致。
  • 复制浏览器的请求头,直接粘贴到代码里,排除头信息缺失的问题。

内容的提问来源于stack exchange,提问作者Bruno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:38:42