我正在尝试在谷歌应用引擎上构建一个维基百科链接爬虫。我想在数据存储中存储索引。但我遇到了 cron 作业和任务队列的 DeadlineExceededError。
对于 cron 作业,我有以下代码:
def buildTree(self):
<pre><code> start=time.time()
self.log.info(" Start Time: %f" % start)
nobranches=TreeNode.all()
for tree in nobranches:
if tree.branches==[]:
self.addBranches(tree)
time.sleep(1)
if (time.time()-start) > 10 :
break
self.log.info("Time Eclipsed: %f" % (time.time()-start))
self.log.info(" End Time:%f" % time.clock())
</code></pre>
我不明白为什么 for 循环在 10 秒后没有中断。它在开发服务器上执行。服务器上的 time.time() 肯定有问题。还有其他功能我可以使用吗?
对于任务队列,我有以下代码:
def addNewBranch(self, keyword, level=0):
<pre><code> self.log.debug("Add Tree")
self.addBranches(keyword)
t=TreeNode.gql("WHERE name=:1", keyword).get()
branches=t.nodes
if level < 3:
for branch in branches:
if branch.branches == []:
taskqueue.add(url="/addTree/%s" % branch.name)
self.log.debug("url:%s" % "/addTree/%s" % branch.name)
</code></pre>
日志显示它们都遇到了 DeadlineExceededError。后台处理时间不应超过页面请求的 30 秒。有没有办法解决异常?
这是 addBranch() 的代码
<p>def addBranches(self, keyword): </p>
<pre><code> tree=TreeNode.gql("WHERE name=:1", keyword).get()
if tree is None:
tree=TreeNode(name=keyword)
self.log.debug("in addBranches arguments: tree %s", tree.name)
t=urllib2.quote(tree.name.encode('utf8'))
s="http://en.wikipedia.org/w/api.php?action=query&titles=%s&prop=links&pllimit=500&format=xml" % t
self.log.debug(s)
try:
usock = urllib2.urlopen(s)
except :
self.log.error( "Could not retrieve doc: %s" % tree.name)
usock=None
if usock is not None:
try:
xmldoc=minidom.parse(usock)
except Exception , error:
self.log.error("Parse Error: %s" % error)
return None
usock.close()
try:
pyNode= xmldoc.getElementsByTagName('pl')
self.log.debug("Nodes to be added: %d" % pyNode.length)
except Exception, e:
pyNode=None
self.log.error("Getting Nodes Error: %s" % e)
return None
newNodes=[]
if pyNode is not None:
for child in pyNode:
node=None
node= TreeNode.gql("WHERE name=:1", child.attributes["title"].value).get()
if node is None:
newNodes.append(TreeNode(name=child.attributes["title"].value))
else:
tree.branches.append(node.key())
db.put(newNodes)
for node in newNodes:
tree.branches.append(node.key())
self.log.debug("Node Added: %s" % node.name)
tree.put()
return tree.branches
</code></pre>
最佳答案
我在 GAE 上的日期时间方面取得了巨大成功。
from datetime import datetime, timedelta
time_start = datetime.now()
time_taken = datetime.now() - time_start
time_taken 将是一个时间增量。您可以将其与具有您感兴趣的持续时间的另一个时间增量进行比较。
ten_seconds = timedelta(seconds=10)
if time_taken > ten_seconds:
....do something quick.
听起来使用 mapreduce 或任务队列会为您提供更好的服务。两者对于处理大量记录都很有趣。
您拥有的代码的更简洁模式是仅获取一些记录。
nobranches=TreeNode.all().fetch(100)
此代码只会提取 100 条记录。如果您已满 100 个,完成后,您可以在队列中添加另一个项目以启动更多项目。
-- 基于关于需要没有 Twig 的树的评论 --
我在那里没有看到你的模型,但如果我试图创建一个没有分支的所有树的列表并处理它们,我会:仅获取 100 个左右 block 中的树的键。然后,我将使用 In 查询获取属于这些树的所有分支。按树键排序。扫描分支列表,第一次找到树的 key 时,从列表中拉出 key 树。完成后,您将获得“无分支”树键的列表。安排其中每一项进行处理。
一个更简单的版本是在树上使用 MapReduce。对于每棵树,找到与其 ID 匹配的一个分支。如果不能,请标记该树以进行后续处理。默认情况下,此函数将拉取具有 8 个并发工作线程的批量树(我认为是 25 个)。而且,它在内部管理作业队列,因此您不必担心超时。
关于python - 维基百科爬虫的 cron 作业和任务队列的应用程序引擎 DeadlineExceededError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3919337/