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

Scrapy登录报错ValueError:无法找到<form>元素,请求协助排查

解决Scrapy无法识别Starngage登录表单的问题

问题原因

该网站的登录表单是通过JavaScript动态渲染生成的。Scrapy默认仅获取服务器返回的原始HTML,不会执行页面中的JS代码,因此你拿到的响应里不存在<form>标签,导致FormRequest.from_response抛出找不到表单的错误。

解决方案

结合你已经监控到手动登录的Payload和请求头,提供两种可行的解决方式:

方式一:直接构造登录POST请求

跳过FormRequest.from_response,直接模拟手动登录时的POST请求,核心要点如下:

  • 从开发者工具中确认登录接口的真实POST地址
  • 带上监控到的表单数据(email、password),若页面存在CSRF令牌,需从登录页面HTML中提取后一并提交
  • 复制浏览器登录时的请求头(如User-Agent、Referer),避免触发反爬

修改后的代码示例:

import scrapy
from scrapy.http import FormRequest

class chnlids(scrapy.Spider):
    name = "chnlids"
    page_number = 0
    # 替换为你监控到的真实登录接口URL
    login_api_url = "https://starngage.com/plus/api/auth/login"

    def start_requests(self):
        # 先请求登录页面,获取可能存在的CSRF令牌
        yield scrapy.Request(
            url='https://starngage.com/plus/en-us/login',
            callback=self.prepare_login
        )
    
    def prepare_login(self, response):
        # 提取CSRF令牌,根据页面实际结构调整选择器
        csrf_token = response.css('input[name="_token"]::attr(value)').get()
        # 构造登录POST请求
        yield FormRequest(
            url=self.login_api_url,
            formdata={
                'email': 'demo',
                'password': 'demo',
                '_token': csrf_token  # 无令牌则删除该行
            },
            headers={
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
                'Referer': 'https://starngage.com/plus/en-us/login'
            },
            callback=self.verify_login
        )

    def verify_login(self, response):
        # 验证登录是否成功(根据响应内容或状态码判断)
        if response.status == 200 or "success" in response.text:
            # 登录成功后启动目标页面爬取
            yield scrapy.Request(
                url='https://starngage.com/plus/en-us/influencer/ranking/youtube/all-countries?page=1',
                callback=self.parse
            )
        else:
            self.logger.error("登录失败,请检查表单数据或请求头")

    def parse(self, response):
        # 修正原代码中i的逻辑错误,直接遍历提取结果
        for channel in response.css("a.text-break::text"):
            yield {
                "channel_id": channel.get()
            }
        
        # 处理翻页逻辑
        if self.page_number < 10:
            self.page_number += 1
            next_page = f'https://starngage.com/plus/en-us/influencer/ranking/youtube/all-countries?page={self.page_number}'
            yield scrapy.Request(next_page, callback=self.parse)

方式二:使用浏览器渲染工具(如Playwright)

若网站登录逻辑复杂(如动态Token、验证码),可结合Playwright模拟真实浏览器行为,自动执行JS渲染表单:

  1. 安装依赖:pip install scrapy-playwright
  2. 在项目settings.py中配置Playwright:
DOWNLOAD_HANDLERS = {
    "http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
    "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
}
PLAYWRIGHT_LAUNCH_OPTIONS = {"headless": False}  # 设为True可启用无头模式
  1. 修改爬虫代码启用Playwright渲染:
import scrapy
from scrapy.http import FormRequest

class chnlids(scrapy.Spider):
    name = "chnlids"
    page_number = 0

    def start_requests(self):
        yield scrapy.Request(
            url='https://starngage.com/plus/en-us/login',
            callback=self.login,
            meta={"playwright": True}  # 启用JS渲染
        )
    
    def login(self, response):
        # 此时响应已完成JS渲染,可正常识别表单
        return FormRequest.from_response(
            response,
            formdata={
                'email': 'demo', 
                'password': 'demo'
            },
            callback=self.parse_after_login
        )

    def parse_after_login(self, response):
        # 登录成功后爬取目标页面,同样启用渲染
        yield scrapy.Request(
            url='https://starngage.com/plus/en-us/influencer/ranking/youtube/all-countries?page=1',
            callback=self.parse,
            meta={"playwright": True}
        )

    def parse(self, response):
        for channel in response.css("a.text-break::text"):
            yield {
                "channel_id": channel.get()
            }
        
        if self.page_number < 10:
            self.page_number += 1
            next_page = f'https://starngage.com/plus/en-us/influencer/ranking/youtube/all-countries?page={self.page_number}'
            yield scrapy.Request(next_page, callback=self.parse, meta={"playwright": True})

额外注意事项

  • 确保请求头的User-Agent与浏览器一致,降低被反爬识别的概率
  • 部分网站会在登录页面设置会话Cookie,需确保POST请求携带该Cookie
  • 原代码中parse方法的i变量逻辑错误(循环内未递增),已在示例中修正

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:27:39