资讯动态

Scrapy入门实战:从创建项目到跑通第一个爬虫的全流程

发布时间:2026/10/17 2:38:57 来源:尧图企业网站定制
写爬虫这块Scrapy算得上Python生态里绕不开的老牌框架。前后有太多人因为它“上手陡峭”而劝退其实说穿了你只要把“创建一个爬虫项目、写一个Spider文件、跑起来看到数据”这三步走通后面所有高级玩法都是在这个基础上加东西。这篇就是Scrapy入门实战笔记重点放在“创建爬虫”这件事上把命令、目录结构、代码写法、运行调试整个链路过一遍。这篇内容适合两类人一是刚学完Python基础、想找个方向练手的同学二是之前用过requests但发现写多页面抓取或者大规模采集时手忙脚乱想换框架的开发者。不论你是哪一种跟着这篇文章把一个能跑的爬虫创建出来你就算正式迈进Scrapy大门了。1. 写Scrapy之前先建立几个基础认知别急着敲命令有两个概念想先聊清楚我发现很多新手卡住的根源都在这里。1.1 Scrapy到底替你做了什么requests写爬虫的时候流程是自己发请求、自己拿响应、自己解析、自己处理翻页、自己管失败重试。单页还好一旦页数多、字段多代码很容易变成一团乱麻。Scrapy的核心思路是把“爬虫”这件事拆成几个模块每个模块只干一件事Spiders定义往哪爬、怎么解析Items定义数据长什么样Pipelines处理数据比如清洗、去重、存库Middlewares在请求和响应中间拦截、加工Engine和Scheduler负责调度请求、控制并发你写的核心代码其实就两部分Spider抓什么、怎么解析和Pipeline数据怎么处理。剩下的框架全帮你兜住了。用生活里的事打比方requests是“你自己开车去买菜”所有路线自己规划Scrapy是“上了一辆公交车你只需要管下车去哪站买什么菜”车怎么跑你不用管。这个认知到位了后面看代码就不会觉得莫名其妙。1.2 安装Scrapy时最容易踩的坑安装本身一行命令的事pip install scrapy但很多人在这里碰壁主要体现在两个地方。一是Python版本。Scrapy对Python版本有要求过老的版本比如3.6以下装新版Scrapy会报找不到对应whl包。建议直接用Python 3.8以上版本省心。二是Windows环境编译问题。部分依赖包比如twisted在Windows上需要预编译的二进制包如果安装过程报Microsoft Visual C 14.0 is required说明你缺C构建工具。最快的解法是去下载对应版本的.whl文件手动安装或者直接装Anacondaconda环境里依赖都是编译好的。提示装完之后在终端敲scrapy version能正常输出版本号就说明环境OK。这一步确认了我才建议继续往下走。1.3 Scrapy项目的核心目录结构用命令创建项目后你会看到下面这堆文件和文件夹。初次接触的人容易懵其实记住几个关键的就行。myproject/ ├── scrapy.cfg ├── myproject/ │ ├── __init__.py │ ├── items.py │ ├── middlewares.py │ ├── pipelines.py │ ├── settings.py │ └── spiders/scrapy.cfg项目配置文件部署时要用平时不用动items.py定义你要提取的数据字段pipelines.py写数据处理逻辑settings.py全局配置比如并发数、下载延迟、UA伪装spiders/放你写的爬虫文件一个网站一个文件也可一个网站多个文件新手阶段不用管middlewares.py那是做反爬策略才用到的。先集中火力把spiders、items、pipelines、settings这四个文件弄明白就够起步了。2. 创建项目的标准动作和背后原理环境没问题了接下来就是实操环节。这里我会把命令和使用原理一块讲了免得你敲完不知道发生了什么。2.1 startproject创建项目骨架打开终端进到你准备存放代码的目录执行scrapy startproject bookspider这条命令会生成一个名为bookspider的项目文件夹。敲完之后你进入这个目录cd bookspider注意后面所有scrapy命令都要在这个目录下执行因为你得让Scrapy找到scrapy.cfg这个配置文件否则它会提示找不到项目。有一个细节容易忽略项目名别用scrapy、test这种词前者会和框架本身冲突后者在某些工具链里也有歧义尽量用语义化命名比如bookspider、news_spider。2.2 genspider创建第一个爬虫文件光有项目骨架还不行你得告诉Scrapy“我要爬哪个网站”。标准做法是scrapy genspider book books.example.com这条命令干了三件事在spiders/目录下创建了book.py文件自动填充了基础模板代码顺便把allowed_domains设置成了books.example.com。生成的模板代码长这样import scrapy class BookSpider(scrapy.Spider): name book allowed_domains [books.example.com] start_urls [https://books.example.com/] def parse(self, response): pass我建议你现在就把start_urls改成实际要爬的入口地址比如图书分类页的URL。改的时候注意URL必须带http://或https://前缀不带的话Scrapy会当成相对路径处理直接报错。2.3 手写Spider文件 vs genspider模板选哪个新手会纠结“到底用命令生成还是自己新建文件”。我的建议是刚入门用genspider写过几个项目之后全部手写。原因很简单。genspider生成的是模板帮你把name、allowed_domains、parse方法这些必备要素都列好了你只需要填空容错率高。但等你熟练以后你会发现模板生成的骨架其实挺死板的比如有些爬虫入口不是多个URL而是需要从某个API拿还有些爬虫不需要parse而是用start_requests方法这时候手写一个Spider会更快。无论用哪种方式Spider类必须有的三个要素是name爬虫唯一标识必须在项目内唯一allowed_domains限定抓取域名范围防止爬到别的网站parse响应处理入口框架把下载好的网页传到这里这三个少了任何一个爬虫都没法正常工作。3. 核心实操从零写一个能跑的Scrapy爬虫这一节是整个笔记的重点。前面建好项目、生成好爬虫文件接下来就是往里面填逻辑。我会用“抓取图书列表页的书名、价格、评分”这个例子演示整个流程走完你就知道Spider、Item、Pipeline三者是怎么配合的。3.1 先定义数据模型把Item写好写爬虫之前先想清楚一个问题你要提取哪些字段这一步很多人偷懒跳过了把数据直接用字典返回短平快可以但项目一旦复杂点就后悔。Item的作用就是给数据一个明确的“结构”。比如抓图书信息在items.py里这么写import scrapy class BookItem(scrapy.Item): title scrapy.Field() price scrapy.Field() rating scrapy.Field()这里定义三个字段title书名、price价格、rating评分。Item结构确定后Spider里返回的数据都是一个模子刻出来的后续Pipeline处理也好写。有人觉得Item多此一举直接yield {title: xxx, price: xxx}多省事。但在真实项目里字段一多就容易手滑写错键名而且Pipeline里引用item[title]的时候如果字典键写错了报错信息会绕一大圈才能发现。用Item之后字段缺失或者拼写错误当场就能暴露。3.2 手写parse解析选择器的第一个坑写parse(self, response)的时候优先搞清楚response里有什么。Scrapy的Response对象有两个高频方法response.xpath()用XPath路径提取节点response.css()用CSS选择器提取节点以提取每本书的信息为例。假设页面里每本书都在article classproduct_pod这个标签下XPath写法是def parse(self, response): for book in response.xpath(//article[contains(class, product_pod)]): item BookItem() item[title] book.xpath(.//h3/a/title).get() item[price] book.xpath(.//p[classprice_color]/text()).get() item[rating] book.xpath(.//p[contains(class, star-rating)]/class).get() yield item这里有几个新手必踩的坑我一个个说。第一个坑XPath开头忘点。看你写book.xpath(.//h3/a/title)那个点.不能丢。它的意思是“从当前节点往下找”没有点就变成“从整个文档找”等于你完全没用到循环里取出来的book节点命中率会错得离谱。第二个坑忘了.get()。xpath()返回的是选择器列表不是字符串。不调用.get()的话你拿到的是一堆Selector对象打印出来全是Selector xpath... dataxxx就跟你点外卖只收到外卖袋没收到饭一样。.get()取第一个匹配结果.getall()取所有这个区分要牢牢记住。第三个坑属性提取和文本提取的表达式不一样。提取链接或属性用属性名比如title、href提取文本内容用text()。混用基本拿不到数据。3.3 翻页处理早期常见方案能提取出第一页的条目不算完真实场景都是几十上百页。Scrapy里处理翻页的思路很直接在当前页面解析响应里找到“下一页”的链接然后用response.follow()继续请求。代码示例如下next_page response.xpath(//li[classnext]/a/href).get() if next_page: yield response.follow(next_page, callbackself.parse)response.follow()会自动处理URL拼接你传进去的next_page即使是相对路径比如page-2.html它也知道拼到当前域名后面去。这一点相当贴心如果自己手动拼URL还得用urljoin容易出错。同时callbackself.parse表示下一页下载完之后继续交给parse处理于是整个爬虫就在这个循环里一级一级地往下一页爬直到没有下一页链接为止。这个翻页写法是Scrapy入门的标志性动作。理解它之后你就算是真的把Spider的“自动抓取”能力握在手里了。3.4 start_requests方法的作用默认情况下Scrapy拿到start_urls列表后会逐个生成Request对象下载完成后直接交给parse处理。但有些场景你需要在请求之前先做一些额外操作比如需要登录后才能访问的页面得先带Cookie需要在URL里注入不同参数需要动态修改请求头这时候就需要覆盖start_requests方法def start_requests(self): for url in self.start_urls: yield scrapy.Request(url, callbackself.parse, headers{User-Agent: Mozilla/5.0})你没覆盖的时候Scrapy从start_urls生成请求也是一样的效果。覆盖之后可以自由控制callback、headers、cookies等参数。入门阶段不用急着用但看到别人代码里有这个方法心里要清楚它存在的意义。4. 数据做完解析之后怎么让它落地很多教程讲到这里就结束了yield item控制台打印一下完事。但真实项目里数据要存文件、进数据库这就轮到Pipeline登场了。4.1 Pipeline的启用逻辑与常见存储姿势在pipelines.py里写一个类import json class BookPipeline: def process_item(self, item, spider): with open(books.jsonl, a, encodingutf-8) as f: line json.dumps(dict(item), ensure_asciiFalse) \n f.write(line) return item注意要让这个Pipeline生效还得在settings.py里打开开关ITEM_PIPELINES { bookspider.pipelines.BookPipeline: 300, }那个数字300是这个Pipeline的执行优先级数字越小越先执行。同一个项目可以配置多个Pipeline比如一个Pipeline做数据清洗、一个做去重、一个做入库就靠这个数字控制先后顺序。我知道有人图省事直接在Spider里把数据写文件不通过Pipeline。这种做法对付一两个脚本还行但如果你后面要同时跑多个Spider每个Spider都写一份存文件的代码重复代码就泛滥了。Pipeline的定位就是“数据落地统一出口”应该在设计阶段就纳入考虑。4.2 用配置直接导出CSV/JSON如果只是本地跑一次不需要写Pipeline那么重Scrapy提供了一个更轻量的方式运行爬虫的时候直接用-o参数指定输出文件。示例scrapy crawl book -o books.csv scrapy crawl book -o books.json框架会根据文件扩展名自动选择输出格式。这个方法做数据验证、快速测试的时候非常方便几乎不写额外代码。但它的问题是每次运行都会覆盖之前的文件。想追加数据或者需要复杂数据处理还是得回到Pipeline。4.3 settings.py里不调会后悔的配置项分享几个我凡是写爬虫必调的配置调完能省掉一堆琐碎问题。ROBOTSTXT_OBEY False这一项默认是True意思是Scrapy会先读网站的robots.txt来决定能不能爬。某些网站robots写得比较粗把不该禁止的路径也禁了新手开着这个选项很容易碰到“页面明明能打开但爬虫就是抓不到数据”的诡异问题。学习期间先关掉它但要明白真正上线做采集时尊重robots协议和网站访问规则是基本素养。DOWNLOAD_DELAY 1给请求加一个间隔时间单位秒。不加这个的话Scrapy默认并发跑起来非常猛有可能给目标站造成压力也不太道德。加了这个之后爬取速度会慢一些但稳定很多也降低被封概率。DEFAULT_REQUEST_HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8, }Scrapy默认的User-Agent是一个无比显眼的Scrapy/版本号很多网站看到这个UA就直接拒绝访问。把它换成一个浏览器UA是入门阶段最有用的反拦截手段。4.4 运行爬虫的完整命令与输出观察运行爬虫就一个命令scrapy crawl book控制台会滚动输出日志包括抓取状态、响应状态码、item信息等。第一次看到控制台刷屏别慌主要看两个指标200代表请求成功item代表解析并yield了一条数据如果日志里出现大量404或者403多半是URL写错或UA被识别了优先检查这两处。想让日志精简一点可以加--nolog参数但调试阶段不建议因为你得靠日志定位问题。5. 调试是入门必修课Scrapy Shell及其他实操心法写了爬虫不代表能跑通跑通了也不代表数据是对的。就我的经验Scrapy入门约一半时间花在调试和排错上。这里分享几个能大幅加速调试的动作。5.1 scrapy shell比打印大法强十倍写XPath最容易出问题但你又不可能每次都把整个爬虫跑起来去验证于是Scrapy提供了一个交互式调试工具—scrapy shell。用法scrapy shell https://books.example.com/它会拉取这个页面然后给你一个交互式环境。你可以在里面测试XPath和CSS表达式 response.xpath(//article[contains(class, product_pod)]) response.xpath(//p[classprice_color]/text()).get()直接把要写的表达式在shell里跑一遍能拿到数据再写回爬虫文件。这个习惯能省掉大量“写完跑一遍、跑完发现拿不到数据、再回去改”的无效循环。5.2 提取不到数据的三个排查方向遇到“爬虫没报错但就是没数据”的情况别急着怀疑代码按照下面这个顺序排查第一先用shell打开目标页面确认能否拿到响应。如果提示403看UA问题如果超时可能是网络限制。这一步排除“请求层面的问题”。第二检查XPath表达式。开发工具里按F12能看到XPath的位置但很多工具给出的XPath是绝对路径非常脆弱比如/html/body/div[2]/div/div[1]/ul/li[1]这种。稍微多一层标签就挂了。尽量自己写基于属性或class特征的相对路径。第三检查页面内容是否由JavaScript动态渲染。如果网页源码里都不包含你要的数据那说明数据是异步加载的这时候单纯靠解析HTML就拿不到。解决办法通常是找到数据真实API接口或者配合渲染工具处理。入门阶段先确认好自己爬的是静态页面。5.3 了解Scrapy的运作流程排查会容易很多Scrapy的整个执行流程我有一个极简版的理解方式你的爬虫先产生Request引擎把Request交给调度器排队然后由下载器下载页面网页响应再交回给你的Spider的parse方法parse方法提取出Item或者生成新的Request循环往复。基于这个思路排查问题时其实就在问自己一句话数据到底是在哪一步丢的是请求没成功、还是响应没解析对、还是item没传回Pipeline一步步定位比瞎改代码有效得多。很多人用Scrapy一开始就扎到反爬策略、分布式这种高级话题里我觉得大可不必。把基础链路先跑通心里对整个流程有数后面进阶才有抓手。6. 收尾前聊几个我后来才想明白的事写爬虫这事情代码本身不难难的是对“数据获取”这件事有边界感。爬虫不是只要技术上能访问就算完还需要考虑网站有没有禁止爬取的声明、请求频率会不会影响对方服务、采到的数据用途是否正当。学技术的同时把这些边界意识一并建立起来我个人觉得是入门阶段就该养成的习惯。再分享一个实操细节每次写新爬虫先小规模验证别一上来就全站开爬。可以先限制只抓一两页数据确认字段、存储逻辑都正确之后再放开翻页和并发。这个习惯帮我避了很多次“数据存了一大半才发现字段不对白跑半小时”的低级错误。另外pipelines.py里的数据处理逻辑尽量写简单点。新手容易在Pipeline里堆砌各种功能格式化、清洗、去重、入库全塞进去结果一旦报错很难定位。先把原始数据存下来后面再慢慢处理和迭代这个思路对个人项目来说更务实。这篇笔记的核心就是“创建爬虫”这个动作从建项目、写Spider、解析页面、翻页处理到数据落地整个过程跑通了你就已经掌握Scrapy最常用的80%的能力。后面要做的更多是围绕实战去积累经验遇到需求再学对应的模块这比一口气啃完所有文档轻松得多。下次再写项目试着别用模板生成直接手写一个Spider文件你会发现对结构的理解比敲十次命令都管用。这一个坎翻过去Scrapy的学习就算是真正入门了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑