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

如何解决Scrapy爬取时出现的HTTP 400 Bad Request错误

解决Scrapy爬取AshbyHQ时的400 Bad Request错误

问题分析

你遇到的400错误是因为请求中包含了硬编码的动态头信息和错误的Content-Length,这些都会被服务器判定为无效请求。具体问题点包括:

  • 手动设置的Content-Length数值和实际payload长度不匹配
  • 硬写的Cookie已经过期
  • Traceparent、X-Datadog-*这类动态追踪头是一次性的,重复使用会触发验证失败
  • 过多冗余头信息增加了被识别为爬虫的概率

解决方案

修改你的爬虫代码,移除不必要的动态头,只保留核心必要字段:

修改后的代码

import scrapy
import json

class GreenhouseSpider(scrapy.Spider):
    name = 'greenhouse'
    allowed_domains = ['jobs.ashbyhq.com']
    start_urls = ['https://jobs.ashbyhq.com/api/non-user-graphql?op=ApiJobBoardWithTeams']
    user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'

    def start_requests(self):
        for url in self.start_urls:
            # 只保留必要的请求头
            headers = {
                'Accept': '*/*',
                'Accept-Language': 'en-US,en;q=0.9',
                'Apollographql-Client-Name': 'frontend_non_user',
                'Apollographql-Client-Version': '0.1.0',
                'Content-Type': 'application/json',
                'Origin': 'https://jobs.ashbyhq.com',
                'Referer': 'https://jobs.ashbyhq.com/quora',
                'User-Agent': self.user_agent
            }
            payload = {
                "operationName": "ApiJobBoardWithTeams",
                "variables": {
                    "organizationHostedJobsPageName": "quora"
                },
                "query": "query ApiJobBoardWithTeams($organizationHostedJobsPageName: String!) {\n  jobBoard: jobBoardWithTeams(\n    organizationHostedJobsPageName: $organizationHostedJobsPageName\n  ) {\n    teams {\n      id\n      name\n      parentTeamId\n      __typename\n    }\n    jobPostings {\n      id\n      title\n      teamId\n      locationId\n      locationName\n      employmentType\n      secondaryLocations {\n        ...JobPostingSecondaryLocationParts\n        __typename\n      }\n      compensationTierSummary\n      __typename\n    }\n    __typename\n  }\n}\n\nfragment JobPostingSecondaryLocationParts on JobPostingSecondaryLocation {\n  locationId\n  locationName\n  __typename\n}"
            }
            yield scrapy.Request(
                url=url,
                method='POST',
                headers=headers,
                body=json.dumps(payload),
                callback=self.parse
            )

关键修改点说明

  • 移除了Content-Length:Scrapy会自动根据body的长度计算并设置这个头,避免手动设置导致的不匹配
  • 删除了过期的Cookie和动态追踪头:这些头是服务器生成的一次性标识,硬写会被拒绝
  • 简化了请求头:只保留服务器验证必需的字段,降低被拦截的风险
  • 统一使用类定义的user_agent,保持请求一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 01:15:37