编写爬虫时,最耗时的往往不是解析页面,而是处理目标站点的反爬虫策略。一个看似简单的请求,可能因为缺少合适的请求头、请求频率过高或IP被标记而返回403。借助ChatGPT生成初始代码,再在Scrapy框架中逐步调试和改造,可以省去大量查文档和试错的时间。但需要明确的是,ChatGPT给出的代码只是起点,真正能稳定运行的爬虫依然依赖对反爬机制的理解和调试经验。

从需求到Scrapy骨架:ChatGPT能帮你做什么
如果直接让ChatGPT写一个完整的爬虫,它通常会返回一个基于Scrapy的示例,包含Spider类、起始URL和解析规则。例如,可以让ChatGPT生成一个抓取列表页标题和链接的爬虫,它会输出类似下面的代码。这个阶段的关键在于把需求描述清楚:目标站点结构、需要提取的字段、是否需要翻页、是否要处理登录或动态内容。提示词越具体,生成的代码越接近可用状态。
import scrapy
class ArticleSpider(scrapy.Spider):
name = 'article'
start_urls = ['https://ipipp.com/articles']
def parse(self, response):
for block in response.xpath('//div[@class="article-item"]'):
yield {
'title': block.xpath('.//h2/a/text()').get(),
'url': block.xpath('.//h2/a/@href').get(),
'summary': block.xpath('.//p/text()').get(),
}
next_page = response.xpath('//a[@class="next"]/@href').get()
if next_page:
yield response.follow(next_page, self.parse)
这段代码可以直接运行,但前提是目标站点没有明显的反爬机制。实际上,多数网站都会校验请求头,甚至要求携带特定的Cookie或Referer。如果直接用默认的Scrapy User-Agent,大概率会在第一页就收到403。此时可以让ChatGPT继续生成自定义下载器中间件,比如添加随机User-Agent、设置请求延迟,或者接入代理。不过,这些绕过手段需要结合具体失败现象来调整,不能盲目堆砌。
ChatGPT的另一个价值在于快速生成模板代码,比如Scrapy中间件、管道或Item定义。你可以让它解释某个错误堆栈,或者把一段requests代码改写成Scrapy风格。但要注意,生成的代码可能包含过时的API或不符合目标站点实际情况的假设,必须逐行检查并在本地运行验证。
反爬虫机制识别与绕过:请求头、代理与动态渲染
常见的反爬虫机制主要分为三类:请求特征校验、行为频率限制和内容渲染保护。请求特征校验包括User-Agent、Referer、Accept-Language等头部字段,以及Cookie中的会话标识。如果请求头看起来不像真实浏览器,服务器会直接拒绝。解决思路是让ChatGPT生成一个随机User-Agent中间件,每次请求时从预置列表中随机选择。下面的代码展示了如何实现,同时可以加入请求延迟,降低频率限制的风险。
import random
from scrapy import signals
class RandomUserAgentMiddleware:
user_agents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
]
@classmethod
def from_crawler(cls, crawler):
middleware = cls()
crawler.signals.connect(middleware.spider_opened, signal=signals.spider_opened)
return middleware
def spider_opened(self, spider):
spider.logger.info('随机User-Agent中间件已启用')
def process_request(self, request, spider):
request.headers['User-Agent'] = random.choice(self.user_agents)
request.headers['Accept-Language'] = 'zh-CN,zh;q=0.9,en;q=0.8'
request.headers['Referer'] = 'https://ipipp.com/'
这段中间件在Scrapy的下载器中间件中生效,每次请求前随机替换User-Agent,并补充Accept-Language和Referer。需要注意的是,Referer不能随意伪造,必须根据实际来源页面来设置,否则某些站点会识别为异常。对于IP频率限制,则需要引入代理池。Scrapy可以通过中间件设置请求的meta中的proxy字段,例如使用本地代理服务,或调用第三方代理API。ChatGPT可以生成一个简单的代理中间件,但代理的稳定性和匿名度需要自己测试。
动态渲染是另一个难点。有些网站的数据由JavaScript异步加载,直接请求HTML拿不到完整内容。此时有几种方案:分析接口直接请求JSON数据、使用Selenium或Playwright渲染页面,或者通过Scrapy对接Splash服务。ChatGPT可以根据目标站点的网络请求给出建议,比如告诉你如何找到XHR接口,或者生成一个简单的Playwright脚本。但要注意,动态渲染会显著增加资源消耗,不适合大规模抓取。
还有一种情况是字体加密、CSS混淆或验证码。对于这类高级反爬,ChatGPT只能提供思路,无法生成直接可用的破解代码。更稳妥的做法是寻找替代数据源,或控制抓取频率,避免触发风控。
Scrapy代码调试:日志、断点与中间件排查实战
当爬虫运行报错或返回空数据时,第一步是开启详细日志。Scrapy默认的日志级别可能隐藏了关键信息,可以在settings.py中设置LOG_LEVEL为DEBUG,或者在运行命令中加-L DEBUG。这样可以看到每个请求的响应状态、重定向信息和解析过程中的异常。如果请求返回403或429,日志中会出现对应记录,有助于判断是请求头问题还是频率问题。
# settings.py 中的调试配置
LOG_LEVEL = 'DEBUG'
DOWNLOAD_DELAY = 2
RANDOMIZE_DOWNLOAD_DELAY = True
CONCURRENT_REQUESTS_PER_IP = 1
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.RandomUserAgentMiddleware': 543,
}
另一个常用工具是scrapy shell,可以直接在命令行交互式测试选择器和响应内容。例如运行scrapy shell "https://ipipp.com/articles",然后在shell中执行response.status、response.text[:500]和response.xpath('//div[@class="article-item"]')来检查数据。如果shell中能取到数据,但爬虫运行时为空,通常是中间件或管道过滤导致的。此时需要检查Item Pipeline、去重过滤器或下载器中间件的执行顺序。
Scrapy的下载器中间件顺序由数字决定,数字越小越靠近引擎,越大越靠近下载器。如果自定义中间件没有生效,先确认是否在DOWNLOADER_MIDDLEWARES中正确注册,并且没有拼错路径。可以在中间件的process_request方法中打印日志,例如spider.logger.info(request.url),观察请求是否经过该中间件。对于异常,可以结合Python的pdb断点或IDE的调试功能,在parse方法中设置断点,查看response对象的具体内容。
如果遇到验证码或登录墙,不要试图用ChatGPT生成破解逻辑。更好的做法是分析目标站点的接口,看是否存在免验证的移动端接口或开放数据源。同时,控制抓取速度、设置合理的下载延迟、尊重robots.txt,能减少很多不必要的反爬对抗。ChatGPT能帮你写出更规范的代码,但合规和稳定性始终需要开发者自己把握。