pyspider的on_finished()函数调用问题
本人的需求是:在操作一批量级比较大的库时,在库中添加了一个字段----是否被读取,每条数据有唯一id标识每一条记录,所以我每次操作完100条数据,就将起是否被读取的状态置为1,之后又去取得未读取的limit 100,循环如此一直到读完整个库。但测试的时候出现了一些问题,如下
from pyspider.libs.base_handler import *
import chardet,urllib
import os,ftplib
from ftplib import FTP
class Handler(BaseHandler):
crawl_config = {
}
start = 0
def on_start(self):
self.crawl('www.baidu.com', callback=self.index_page,force_update=True)
@every(minutes=24 * 60)
def index_page(self, response):
for each in list(response.doc('a[href^="http"]').items())[0:1]:
self.start += 1
self.crawl(each.attr.href, callback=self.detail_page,force_update=True)
ftp_connect(self.start)
@config(priority=2)
def detail_page(self, response):
return {
"url": response.url,
"title": response.doc('title').text(),
}
def on_finished(self, response, task):
#pass
#在这里改写回显操作
ftp_connect(self.start)
self.on_start()
def ftp_connect(start):
ftp_server = "192.168.218.10"
username = "ftpuser"
password = "password"
ftp = FTP()
ftp.set_debuglevel(0)
ftp.connect(ftp_server,21)
ftp.login(username,password)
#现在本地写一个temp.text文件,将其内容读出,传到服务器的ftp路径下,再删除temp.text文件
a = open("temp.txt","wb").write("%d"%start)
a = open("temp.txt","rb")
ftp.storbinary("STOR lyric.txt",a)
os.system("rm -f temp.txt")
return None
如上代码,我在on_finished()中进行操作时候,发现其self.start并没有按照正常的值去返回,初始化值为0,在index_page()函数中进行过 +=1 操作,本应该是1,可是最后在ftp路径下查看的文件中的值是0或1(还出现2,3...),如下图
如上的结果,导致我在回写数据库(将是否被读取置为已读取)的时候出错,一个100条记录的任务需要执行多次才能全部置为已读取。也就是一个页面要抓取多次(大概5,6次....),暂时的解决方法是在读取完库之后立即回写,而不是在on_finished()中回写。但还是希望能了解到为什么on_finished()会出现这样的问题.
想请问下BaseHandler的运行方式,现在也正在看/pyspider/libs/base_handler.py,问题先挂出来,之后有了自己的想法再填充,希望大家能帮忙给点思路:比如class Handler(BaseHandler) 类是如何切换到task的,其中的各个def又是怎么转换成task....
先行谢谢了
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
脚本的设计是分布式的,所以运行时不保证 Handler 只有单个实例,并且这个实例不会被重建。
所以使用 Handler 类的成员变量,它的行为是不确定的。
如果有在脚本内部保存状态的需求,我在公司项目中实现过一个类似浏览器 JS 的 localStorage 的类,它后端位于 redis 中,可以使用它在脚本间共享数据。