在 scrapy 中,怎么让 yield Request(url,callback)中的 callback 函数执行完成后才执行 yield Request(url,callback)其后的语句? - V2EX
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
scb20100708
V2EX    Python

在 scrapy 中,怎么让 yield Request(url,callback)中的 callback 函数执行完成后才执行 yield Request(url,callback)其后的语句?

  •  
  •   scb20100708 2017 年 11 月 17 日 7200 次点击
    这是一个创建于 2976 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我需要先用回调函数 callback 改变类变量,然后使用类变量,但发现程序的实际执行是不等待 yield Request(url,callback)中的 callbak 函数执行完成,便执行其后的语句了。怎么办呢?

    写了个程序来表达我的意图:

    # -*- coding: utf-8 -*- from scrapy import Spider, Request class ZhihuSpider(Spider): name = "debug_zhihu" allowed_domains = ["www.zhihu.com"] list_for_test = [] def start_requests(self): yield Request('https://www.zhihu.com/people/excited-vczh/following', self.change_list) print('after sent Request statement,list_for_test:', self.list_for_test) # 想打印出“[0,1,2,3,4]”,结果打印出"[]" def change_list(self): for each_item in range(0, 5): self.list_for_test.append(each_item) 
    14 条回复    2017-11-18 16:59:18 +08:00
    scb20100708
        1
    scb20100708  
    OP
       2017 年 11 月 17 日
    发现补充中的代码错了,def change_list(self):应是 def change_list(self,response):
    改后也输出不了想输出的"[0,1,2,3,4]"
    leavic
        2
    leavic  
       2017 年 11 月 17 日
    把 print 写进 callback 函数的最后。。。。。
    scb20100708
        3
    scb20100708  
    OP
       2017 年 11 月 17 日
    @leavic
    还有别的方法吗?实际代码还有函数“ change_list2 ”也要改变类变量,想在所有改变执行完后再处理类变量。
    860670496
        4
    860670496  
       2017 年 11 月 17 日
    请参考:
    https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317799226173f45ce40636141b6abc8424e12b5fb27000

    如果一个函数定义中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个 generator:

    这里,最难理解的就是 generator 和函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成 generator 的函数,在每次调用 next()的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行。

    所以直接用啃 scrapy 的方法来学 python 不是个好选择,这个坑我也掉过,就是看教程的时候完全是表面上的理解生成器的概念,一用起来就傻了,必须得动手写几个才能彻底明白
    knightdf
        5
    knightdf  
       2017 年 11 月 17 日
    把 yield Request(url,callback)其后的语句放在 callback 的后面执行
    leavic
        6
    leavic  
       2017 年 11 月 17 日   1
    @scb20100708 没有什么好方法了,你的需求就应该是把函数放进 callback 里面。
    iyaozhen
        7
    iyaozhen  
       2017 年 11 月 17 日 via Android
    只能 callback 吧。回调地狱就是那么来的
    scb20100708
        8
    scb20100708  
    OP
       2017 年 11 月 17 日
    @860670496
    你给的参考资料看过了,我想不是 yield 的问题,因为 callback 函数会执行,只不过在 callback 函数执行前就执行 yield Request(url,callback)后的语句了。
    @leavic @knightdf @iyaozhen
    好的,谢谢各位
    hcnhcn012
        9
    hcnhcn012  
       2017 年 11 月 17 日 via iPhone
    机制就是这样,为了效率,要是你 callback 里面花了一个很长时间的的 IO 操作,整个框架都在等你的 callback 然后 yield 带出从而发生阻塞那效率会很低,具体怎么实现的话就要结合 twisted 看源码了
    RadishWind
        10
    RadishWind  
       2017 年 11 月 17 日
    还没有实验 加个修饰器行不行?在修饰器中等待?
    NLL
        11
    NLL  
       2017 年 11 月 17 日
    scrapy 是异步的,reuqest 请求也是放进队列的
    larsenlouis
        12
    larsenlouis  
       2017 年 11 月 17 日   1
    “回调函数 callback 改变类变量,然后使用类变量”
    是发出单个请求->callback 链->print,还是发出所有的请求->完成每个请求的 callback 链->print ?
    后者可以用 def spider_closed(self, spider) 参考 https://doc.scrapy.org/en/latest/topics/signals.html
    scb20100708
        13
    scb20100708  
    OP
       2017 年 11 月 17 日
    @hcnhcn012
    谢谢,twisted 还没用过,这个问题先搁这儿吧
    @RadishWind
    感觉和把 print 语句放在 callback 中一样,谢谢哈
    @zhijiansha
    谢谢
    scb20100708
        14
    scb20100708  
    OP
       2017 年 11 月 18 日
    @larsenlouis
    谢谢,我想要实现的正是你说的“发出所有的请求->完成每个请求的 callback 链->print ? “。
    方法可行,谢谢啦。
    还找到了一个办法,直接在类中加个函数:
    def closed(self, reason):
    print(list_for_test)
    参考:
    https://stackoverflow.com/a/33312325/7011350
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2864 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 00:18 PVG 08:18 LAX 16:18 JFK 19:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86