豆瓣电影爬虫踩坑复盘
我做了什么
学爬虫有一阵子了,一直停留在写单文件脚本的阶段,感觉基础不牢。这次想通过一个小项目,把整个流程工程化。
目标选了豆瓣电影 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循环里面了,导致每存一条就关闭一次连接。 - 解决:把
commit和close移到循环外面,等所有数据都执行完再统一提交和关闭。 - 总结:记住一个原则:循环内只做一件事,资源管理在循环外
坑3:去重后计数不准
- 现象:明明用
INSERT IGNORE做了去重,但终端打印的“成功存入”数量还是不对。 - 原因:计数器
num += 1写在try块里,即使数据被IGNORE跳过了,代码也没报错,计数器照样加 1。 - 解决:用
cursor.execute()的返回值affected_rows来判断。affected_rows == 1才说明真正插入了一条数据,这时候才计数。 - 总结:不要相信计数器,要相信数据库的返回值。
代码
完整代码已开源在 GitHub,每个文件都有注释:
github.com/ty153/pytho…