V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
saximi
V2EX  ›  Python

请问用 scrapy 框架写爬虫时,应该如何关闭数据库游标和数据库连接才安全?

  •  
  •   saximi · 2017-10-11 20:00:39 +08:00 · 3138 次点击
    这是一个创建于 2603 天前的主题,其中的信息可能已经有所发展或是发生改变。
    用 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
    
    9 条回复    2017-10-13 23:34:53 +08:00
    sunchen
        1
    sunchen  
       2017-10-11 20:21:52 +08:00
    pipeline 实现 close_spider 方法
    sunchen
        2
    sunchen  
       2017-10-11 20:23:05 +08:00
    写库过程写到 pipeline 里, pipeline 实现 close_spider 方法
    Lax
        3
    Lax  
       2017-10-11 20:27:42 +08:00
    别的语言异常处理都是用 catch
    anguslg
        4
    anguslg  
       2017-10-12 10:48:13 +08:00
    吐槽一下楼主的 md 排版 问题描述至少换个行吧,别人看起来也方便
    saximi
        5
    saximi  
    OP
       2017-10-12 20:44:46 +08:00
    @sunchen 谢谢指点,关于这个做法,我有疑问。例如下面这三个方法返回的对象,如果在爬虫主程序中和 pipelines.py 中都要访问,要如何才能在两个文件之间正确传递呢?
    pymysql.connect()
    pymysql.connect().cursor()
    webdriver.Chrome()
    saximi
        6
    saximi  
    OP
       2017-10-12 20:45:29 +08:00
    @sunchen 因为 pipelines.pymiddlewares.py 中都可以定义这两个方法:open_spider()、close_spider()。
    那么如果两个文件中同名方法的处理逻辑出现冲突了怎么办呢?
    saximi
        7
    saximi  
    OP
       2017-10-12 20:47:05 +08:00
    @anguslg 呵呵,真不好意思,我的主贴中虽然把问题描述分为了三个段落,但是每行内容确实很长,下回我会注意让每行内容不要太长的。
    sunchen
        8
    sunchen  
       2017-10-13 14:19:09 +08:00
    @saximi 建议分开,如果因为某些原因必须同时持有同一个 connection 对象的话,用 spider 对象持有,pipeline 和 middleware 都已访问到,pipelines 和 middleware 中的方法不会冲突的
    saximi
        9
    saximi  
    OP
       2017-10-13 23:34:53 +08:00
    @sunchen 您说的 spider 对象就是 pipeline 中的 self 对象吧?
    如果不是的话,能否举例告知 spider 对象中的什么属性可以存放上述三个方法返回的对象呢?

    关于不同文件中同名方法的冲突,我担心的是 pipelines.pymiddlewares.py 中都有这两个方法时:open_spider()、close_spider(),比如开发人员一时粗心,在 pipelines.py 的 open 方法中将某个变量赋 A 值,但是在 middlewares.py 中的 open 方法中又将整个变量赋 B 值,此时就会出现冲突了,到底实际运行起来,会以哪个文件中的方法为准呢?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4532 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 10:11 · PVG 18:11 · LAX 02:11 · JFK 05:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.