好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

在Google App Engine中使用hash和marshal持久化模块,快速判断数据库条目是否

在Google App Engine中使用hash和marshal持久化模块,快速判断数据库条目是否已经存在

由于要取消linode但是ror的监控程序就不能用了,于是想用gae写一个,毕竟本地电脑太不靠谱了,还要一直开着,


http://blog.csdn.net/egg90/archive/2010/08/16/5816453.aspx


本人在用GAE写爬虫的时候,遇到判断重复URL来防止重复抓取的问题,但是由于GAE数据库的限制(db.ListProperty每个记录不能 保存超过5000个元素),经测试发现直接筛选数据库中的属性来判断是否有重复链接 会耗费大量CPU时间(甚至有时候会花费0.3秒来判断是否已经抓过某个网页),而利用建立哈希表来解决也没有多少改善.

经分析,根本问题在于hash颗粒度太小,读取数据库时使用GQL难免会比 (url in list)这样的python内置语句慢.经过查阅相关资料,用memcache可以解决.因为memcache是保存在内存中的,所以它的效率很高,且 不随请求完毕而消亡.但是memcache有1M大小的限制,而且它并不是永久持久化的.可能因为服务器原因而丢失老数据.

有另一种解决方案就是把hash_list存到一个包装好的raw数据包中,put到数据库,下次使用再展开...于是我找到了marshal模块.它有将python所有内置数据类型和数据结构打包的功能.

注:另外一个python持久化的模块叫pickle 还有其C的底层实现:cPickle,与marshal模块不同的是,它可以记录自定义模块的数据.且展开时要导入原来的模块,若导入失败会引发一个异常.

利用python的marshal内置模块构建dump

view plain copy to clipboard print ?

import  marshal   from  google.appengine.ext  import  db   # 新建模型    class  Dump(db.Model):       dump_str = db.BlobProperty()   #把dump存入list    hash_list = []   for  url  in  urls:       hash_list.append(hash(url))   dump_str = marshal.dumps(hash_list)   Dump( dump_str = dump_str ).put()  

import marshal from google.appengine.ext import db # 新建模型 class Dump(db.Model): dump_str = db.BlobProperty() #把dump存入list hash_list = [] for url in urls: hash_list.append(hash(url)) dump_str = marshal.dumps(hash_list) Dump( dump_str = dump_str ).put()

以下是判断是否存在url记录的方法:


view plain copy to clipboard print ?

url =  "http://xxx.xxx.xxx/xx"    dump = Dump.all().get()   exist =  False    if  dump:        try :           hash_list = marshal.loads(dump.dump_str)        except :            break          # load error         if  hash(url)  in  hash_list:           exist =  True   

url = "http://xxx.xxx.xxx/xx" dump = Dump.all().get() exist = False if dump: try: hash_list = marshal.loads(dump.dump_str) except: break # load error if hash(url) in hash_list: exist = True  

此方法用time测试 每个in 判断的操作需要时间小于0.001s

hash的list空间占用还是很小的,以每个数据记录为2M,每个hash数位64位(8字节)整形,打包不浪费空间,这样计算的话,能记录2*1024^3 /8 = 268435456 条hash数据

等空间不够时,还可以用zlib压缩一下,经过测试可以变成大小的1/3到1/4 ,证明marshal打包后 压缩空间还是蛮大的 毕竟全部是hash数组成的list 

再多的数据便要有更多的Dump项来实现了.

但是这个方法也不是很高效,因为每次还要抓一下数据库或者这个包,希望懂GAE的大侠指正或建议.

查看更多关于在Google App Engine中使用hash和marshal持久化模块,快速判断数据库条目是否的详细内容...

  阅读:33次

上一篇: 谋 定而 动

下一篇:区域性的电子商务