用 scrapy 框架中的 Spider 模版来写爬虫,爬网页过程中将数据插入到数据库里,为了能在正常结束和异常中断的情况下都能关闭数据库游标和数据库连接,我在 start_requests 方法中用了 try 和 finally 语句,在 try 中返回 Request 对象,在 finally 中关闭游标和数据库连接。程序的大致结构如下,其中一些操作用汉字来描述了。
实际运行时,执行到 parse()中的将 item 值插入数据库时报错,提示游标未打开。
发现是因为在执行 yield Request()语句时,会先运行 finally 中的语句,然后才执行 parse()方法,从而使得游标在 finally 中先被关闭,进而报错。
恳请大家指点,大家在用 Spider 模板写爬虫时,为了确保在正常和异常状态下都能关闭游标和数据库连接,这些关闭的操作都是放在哪里实现的呢?
感谢!
class MySpider(Spider):
连接数据库的语句
打开游标的语句
def start_requests(self):
driver.get(url)
try:
yield Request(url=url, callback=self.parse)
finally:
关闭游标的语句
关闭数据库连接的语句
def parse(self, response):
解析页面元素并赋值给 item 字典对象
将 item 的值插入到数据库中
yield item
1
sunchen 2017-10-11 20:21:52 +08:00
pipeline 实现 close_spider 方法
|
2
sunchen 2017-10-11 20:23:05 +08:00
写库过程写到 pipeline 里, pipeline 实现 close_spider 方法
|
3
Lax 2017-10-11 20:27:42 +08:00
别的语言异常处理都是用 catch
|
4
anguslg 2017-10-12 10:48:13 +08:00
吐槽一下楼主的 md 排版 问题描述至少换个行吧,别人看起来也方便
|
5
saximi OP @sunchen 谢谢指点,关于这个做法,我有疑问。例如下面这三个方法返回的对象,如果在爬虫主程序中和 pipelines.py 中都要访问,要如何才能在两个文件之间正确传递呢?
pymysql.connect() pymysql.connect().cursor() webdriver.Chrome() |
6
saximi OP @sunchen 因为 pipelines.py 和 middlewares.py 中都可以定义这两个方法:open_spider()、close_spider()。
那么如果两个文件中同名方法的处理逻辑出现冲突了怎么办呢? |
7
saximi OP @anguslg 呵呵,真不好意思,我的主贴中虽然把问题描述分为了三个段落,但是每行内容确实很长,下回我会注意让每行内容不要太长的。
|
8
sunchen 2017-10-13 14:19:09 +08:00
@saximi 建议分开,如果因为某些原因必须同时持有同一个 connection 对象的话,用 spider 对象持有,pipeline 和 middleware 都已访问到,pipelines 和 middleware 中的方法不会冲突的
|
9
saximi OP @sunchen 您说的 spider 对象就是 pipeline 中的 self 对象吧?
如果不是的话,能否举例告知 spider 对象中的什么属性可以存放上述三个方法返回的对象呢? 关于不同文件中同名方法的冲突,我担心的是 pipelines.py 和 middlewares.py 中都有这两个方法时:open_spider()、close_spider(),比如开发人员一时粗心,在 pipelines.py 的 open 方法中将某个变量赋 A 值,但是在 middlewares.py 中的 open 方法中又将整个变量赋 B 值,此时就会出现冲突了,到底实际运行起来,会以哪个文件中的方法为准呢? |