豆瓣电影 Top250 爬虫:从单脚本到模块化的踩坑复盘

9 阅读2分钟

豆瓣电影爬虫踩坑复盘

我做了什么

学爬虫有一阵子了,一直停留在写单文件脚本的阶段,感觉基础不牢。这次想通过一个小项目,把整个流程工程化。

目标选了豆瓣电影 Top250,数据结构清晰,适合练手。参考 Scrapy 的思路,我把项目拆成了四个文件:

  • config.py:配置管理(数据库连接,请求头,页数)
  • soider.py:页面抓取与数据解析
  • storage.py:数据库初始化与数据的存储
  • main.py:调度入口

这样改了抓取逻辑,数据库那块完全不用动,维护起来方便多了。

踩坑记录

坑1:模块间数据如何传递

  • 现象:spider.py的采集数据不知怎么传递给storage.py
  • 原因:俩模块是独立文件,没有想清楚数据流怎么走
  • 解决:在 spider.py 里把抓取逻辑封装成函数,返回字典列表;在 main.py 里调用这个函数,把返回值直接传给 storage.py 的存储函数。简单直接。
  • 总结:后来才知道模块化不仅仅是拆开功能就完了,还要清楚数据流怎么走

坑2:数据库连接老是断开

  • 现象:存完一条数据后,第二条就开始报错,数据库连接断了
  • 原因:把 conn.commit()conn.close() 写在 for 循环里面了,导致每存一条就关闭一次连接。
  • 解决:把 commitclose 移到循环外面,等所有数据都执行完再统一提交和关闭。
  • 总结:记住一个原则:循环内只做一件事,资源管理在循环外

坑3:去重后计数不准

  • 现象:明明用 INSERT IGNORE 做了去重,但终端打印的“成功存入”数量还是不对。
  • 原因:计数器 num += 1 写在 try 块里,即使数据被 IGNORE 跳过了,代码也没报错,计数器照样加 1。
  • 解决:用 cursor.execute() 的返回值 affected_rows 来判断。affected_rows == 1 才说明真正插入了一条数据,这时候才计数。
  • 总结:不要相信计数器,要相信数据库的返回值。

代码

完整代码已开源在 GitHub,每个文件都有注释:
github.com/ty153/pytho…