如何使用FastAPI集成Scrapy创建API并解决运行异常问题
FastAPI对接Scrapy搜索爬虫故障修复方案
访问异常修复
先解决服务能启动但无法访问的问题,两个基础配置错误:
- 点击终端输出的地址打开文件资源管理器:是Windows终端的协议关联bug,和服务本身无关,不要点击终端里的链接即可。
- 手动输入地址超时:你输错了IP,服务监听的是
127.0.0.1,你输入的127.0.0.0是保留网段地址,不是本机回环地址,正确访问地址是http://127.0.0.1:8000,输对后即可正常访问。
Scrapy对接报错核心修复
你之前把独立启动的CrawlerProcess放到if __name__ == "__main__":块的调整是正确的,剩下的报错基本都是事件循环冲突、传参方式错误导致的,按下面步骤修改:
不要直接在接口函数里用CrawlerProcess跑爬虫
Scrapy依赖的Twisted reactor和uvicorn的异步事件循环默认冲突,每次请求都新建CrawlerProcess会直接触发ReactorNotRestartable报错,推荐用CrawlerRunner做对接,在FastAPI启动时一次性初始化reactor,避免重复启动:
from fastapi import FastAPI from scrapy.crawler import CrawlerRunner from scrapy.utils.log import configure_logging from twisted.internet import reactor import threading # 替换成你自己的爬虫类导入路径 from your_spider_file import SearchSpider app = FastAPI() configure_logging() # 全局只初始化一次runner runner = CrawlerRunner() # 后台线程启动Twisted reactor,不阻塞uvicorn服务 def start_reactor(): reactor.run(installSignalHandlers=False) threading.Thread(target=start_reactor, daemon=True).start() # 临时存储爬取结果,生产环境替换成Redis或数据库 result_cache = {} @app.get("/search") def get_search_result(keyword: str): # 把关键词、结果缓存对象作为参数传给爬虫 crawl_task = runner.crawl(SearchSpider, keyword=keyword, cache=result_cache) # 爬取完成后返回结果 crawl_task.addCallback(lambda _: {"keyword": keyword, "data": result_cache.pop(keyword, [])}) return crawl_task.result
爬虫端正确接收传参
不要修改start_requests的默认方法签名,通过爬虫类的__init__方法接收外部传入的参数:
import scrapy class SearchSpider(scrapy.Spider): name = "search_spider" def __init__(self, keyword=None, cache=None, *args, **kwargs): super().__init__(*args, **kwargs) self.keyword = keyword self.cache = cache # 替换成你实际要爬的搜索引擎地址 self.start_urls = [f"https://your-target-search-site.com/search?q={keyword}"] def parse(self, response): parse_result = [] # 替换成你自己的结果解析逻辑 for item in response.css("div.search-result-item"): parse_result.append({ "title": item.css("h3.title::text").get(), "link": item.css("a::attr(href)").get(), "abstract": item.css("div.abstract::text").get() }) # 把解析完的结果存入缓存 if self.keyword and self.cache is not None: self.cache[self.keyword] = parse_result yield from parse_result
常见报错排查
- 报
ReactorNotRestartable:检查是不是在接口请求逻辑里重复初始化了CrawlerRunner/CrawlerProcess,或者重复调用了reactor.run(),必须保证reactor只在服务启动时启动一次 - 爬虫收不到关键词参数:检查
runner.crawl()传参时是不是把参数作为关键字参数传入,爬虫类的__init__方法有没有正确接收参数并赋值给实例属性 - 接口返回空结果:检查是不是没等爬取任务完成就直接读取缓存返回,必须等crawl的deferred任务执行完再读结果
内容的提问来源于stack exchange,提问作者keni
相关产品推荐
相关产品推荐

