【问题标题】:python script optimization for app engine应用引擎的python脚本优化
【发布时间】:2009-11-27 15:20:38
【问题描述】:

我有以下脚本用于从我的 uni 网站抓取数据并插入到 GAE Db 中

from mechanize import Browser
from BeautifulSoup import BeautifulSoup
import re
import datetime

__author__ = "Nash Rafeeq" 

url  = "http://webspace.apiit.edu.my/schedule/timetable.jsp"
viewurl  = "http://localhost:8000/timekeeper/intake/checkintake/"
inserturl = "http://localhost:8000/timekeeper/intake/addintake/"
print url
mech =  Browser()
try:
    page = mech.open(url)
    html = page.read()
except Exception, err:
    print str(err)
#print html 
soup = BeautifulSoup(html)
soup.prettify() 
tables  = soup.find('select')
for options in tables:
    intake = options.string
    #print intake
    try:
        #print viewurl+intake
        page = mech.open(viewurl+intake)
        html = page.read()
        print html
        if html=="Exist in database":
            print intake, " Exist in the database skiping"
        else:
            page = mech.open(inserturl+intake)
            html = page.read()
            print html
            if html=="Ok":
                print intake, "added to the database"
            else:
                print "Error adding ",  intake, " to database"
    except Exception, err:
        print str(err)

我想知道优化此脚本的最佳方法是什么,以便我可以在应用引擎服务器上运行它。事实上,它现在正在抓取 300 多个条目,并且需要 10 多分钟才能将所有数据插入到我的本地机器上

用于存储数据的模型是

class Intake(db.Model):
    intake=db.StringProperty(multiline=False, required=True)
    #@permerlink    
    def get_absolute_url(self):
        return "/timekeeper/%s/" % self.intake
    class Meta:
        db_table = "Intake"
        verbose_name_plural = "Intakes"
        ordering = ['intake']

【问题讨论】:

    标签: python google-app-engine


    【解决方案1】:

    Divide and conquer.

    1. 制作任务列表(例如要抓取/解析的网址)
    2. 将您的任务添加到队列中(appengine taskqueue apiamazon sqs、...)
    3. 处理您的队列

    【讨论】:

    • 它只是从一个 url 抓取。正在抓取的是超过 300 个条目的选项列表。所以如果我把它分成任务,它将是两个任务。我猜一个用于刮擦,一个用于插入。这会在不达到配额限制的情况下工作吗?或者是他们的另一种优化方式。这里是菜鸟,所以请多多包涵
    • 在您粘贴的代码中,您在 for 循环中执行重复请求 - 所以它不仅仅是一次提取。
    • 等待...您正在发出这些 HTTP 请求以更新数据。删除这些会减少你的运行时间很多
    • 基本上你必须将你的问题分成小到足以在一个请求中处理的任务。似乎您正在尝试在一个请求中执行 300 多个请求(每个选项一个)。如果这需要太长时间,我不会感到惊讶。所以我会为选项列表做一个请求,构建 url 来解析和排队解析任务。然后一次抓取一个网址/选项。
    • 当然,正如 Nick Johnson 已经提到的,如果您在 appengine 上托管脚本,您将能够访问数据存储而无需 http 往返 :) 我认为这些请求正在访问外部应用程序。
    【解决方案2】:

    您应该做的第一件事是重写您的脚本以直接使用 App Engine 数据存储区。您花费的大部分时间无疑是因为您使用 HTTP 请求(每个条目两个!)将数据插入数据存储。直接将数据存储与 batch puts 一起使用应该可以将您的运行时间减少几个数量级。

    如果您的解析代码仍然太慢,您可以将工作分成块并使用task queue API 在多个请求中完成工作。

    【讨论】:

      【解决方案3】:

      嗨,根据 tosh 和 nick 的说法,我已将脚本修改如下

      from google.appengine.api import urlfetch
      from BeautifulSoup import BeautifulSoup
      from timkeeper.models import Intake
      from google.appengine.ext import db
      
      __author__ = "Nash Rafeeq" 
      
      url  = "http://webspace.apiit.edu.my/schedule/timetable.jsp"
      try:
          page = urlfetch.fetch(url)
          #print html 
          soup = BeautifulSoup(page.content)
          soup.prettify() 
          tables  = soup.find('select')
          models=[]
          for options in tables:
              intake_code = options.string
              if Intake.all().filter('intake',intake_code).count()<1:
                  data = Intake(intake=intake_code)
                  models.append(data)
          try:
              if len(models)>0:
                  db.put(models)
              else:
                  pass 
          except Exception,err:
              pass
      except Exception, err:
          print str(err)
      

      我在正确的轨道上吗?我也不确定如何按计划(每周一次)调用它,最好的方法是什么?

      感谢您的及时回答

      【讨论】:

      猜你喜欢
      • 2016-07-16
      • 2011-05-14
      • 2011-08-13
      • 2014-06-25
      • 1970-01-01
      • 2010-10-01
      • 2011-06-05
      • 1970-01-01
      相关资源
      最近更新 更多