Наконец-то пришло озарение и я осилил доку по хранилищу. Вообщем этот пост формально ничего нового не будет содержать а здесь будет лишь только работа над ошибками. Первое что надо учесть, что в классе Model до чёртиков зарезервированных слов.
Так же зарезервировано подчёркивание где-только можно, надо быть с ним аккуратней. Итак как как в блоге не стоит цель сделать ревью сервисам гугл, а лишь практическое использование, то описание классов будет кратким:
Model - аналог таблицы
Expando - динамический класс, в котором хранятся объекты с различными свойствами.
PolyModel - это класс Model, с полиморфизмом.
ReferenceProperty - свойство которое используется как ссылка на другой объект и хранит его ключ. Непосредственно у ключей есть названия, я так понял это и есть способ обеспечить уникальность объектам. Как вы заметили на всё это ушёл без малого один день, но за этот день поменялась архитектура приложения, и появились так же некоторые идеи. Что мы имеем сегодня.
Листинг models.py:
Листинг news.py:
Листинг tasks.py:
.*? ", re.I|re.S)
rt = re.compile("<.*?>", re.I)
res = urlfetch.fetch(trend_url)
if res.status_code != 200:
abort(404)
content = res.content
trends = rl.findall(content)
trends = [rt.sub("", t).strip() for t in trends]
for t in trends:
item = Trends()
item.trend = t
for n in get_news(t):
item.news.append(News.get_or_insert(n["url"], **n).key())
item.video = []
item.ct = ""
item.cf = ""
item.put()Этот скрипт вызывается кроном. И основной файл совсем похудел. Кстати, вынужден вас огорчить, или может обрадовать. Целиком файлы всего приложения публикуются в последний раз, это что бы сформировалось понимания всего приложения. В дальнейшем, что б не громоздить куски кода, это будут только новые методы или классы и может быть редко полностью файлы.
Листинг main.py:
Так же зарезервировано подчёркивание где-только можно, надо быть с ним аккуратней. Итак как как в блоге не стоит цель сделать ревью сервисам гугл, а лишь практическое использование, то описание классов будет кратким:
Model - аналог таблицы
Expando - динамический класс, в котором хранятся объекты с различными свойствами.
PolyModel - это класс Model, с полиморфизмом.
ReferenceProperty - свойство которое используется как ссылка на другой объект и хранит его ключ. Непосредственно у ключей есть названия, я так понял это и есть способ обеспечить уникальность объектам. Как вы заметили на всё это ушёл без малого один день, но за этот день поменялась архитектура приложения, и появились так же некоторые идеи. Что мы имеем сегодня.
[trendec@localhost trendstat]$ ls -al total 284 drwxrwxr-x 4 trendec trendec 4096 May 20 21:42 . drwxr-xr-x 9 trendec trendec 4096 May 17 23:21 .. -rw-r----- 1 trendec trendec 380 May 20 12:41 app.yaml -rwxr-xr-x 1 trendec trendec 98154 May 14 00:26 bottle.py -rw-r--r-- 1 trendec trendec 114796 May 18 19:47 bottle.pyc -rw-r--r-- 1 trendec trendec 96 May 19 15:25 cron.yaml -rwxrwxrwx 1 trendec trendec 471 May 20 21:30 index.yaml -rwxr-x--- 1 trendec trendec 633 May 20 21:27 main.py -rw-r--r-- 1 trendec trendec 515 May 20 19:38 models.py -rw-r--r-- 1 trendec trendec 1051 May 20 19:38 models.pyc -rw-r--r-- 1 trendec trendec 1796 May 20 19:49 news.py -rw-r--r-- 1 trendec trendec 2244 May 20 19:49 news.pyc -rw-r--r-- 1 trendec trendec 141 May 19 23:40 settings.py -rw-r--r-- 1 trendec trendec 247 May 20 00:36 settings.pyc drwxrwxr-x 2 trendec trendec 4096 May 18 20:36 static -rw-r--r-- 1 trendec trendec 759 May 20 19:44 tasks.py -rw-r--r-- 1 trendec trendec 1297 May 20 19:48 tasks.pyc drwxrwxr-x 2 trendec trendec 4096 May 20 17:57 viewsУже явно прослеживается разбиение задач на подзадачи по списку файлов. А так же в детелях.
Листинг models.py:
#!/usr/bin/env python # encoding: utf-8 from google.appengine.ext import db class News(db.Model): title = db.StringProperty() url = db.LinkProperty() domain = db.LinkProperty() publisher = db.StringProperty() image = db.StringProperty() content = db.StringProperty() time = db.DateTimeProperty() class Trends(db.Model): trend = db.StringProperty() time = db.DateTimeProperty(auto_now=True) video = db.StringListProperty() news = db.ListProperty(db.Key) ct = db.TextProperty() cf = db.TextProperty()Таким образом все модели вынесли в отдельный файл
Листинг news.py:
#!/usr/bin/env python
# encoding: utf-8
from google.appengine.api import urlfetch
from urllib import quote
from settings import GOOLE_KEY
from datetime import datetime
from datetime import timedelta
import re
try:
import json
except ImportError:
import simplejson as json
def get_news(key):
news = []
rt = re.compile("<.*?>", re.I)
rd = re.compile("^http://[^/]+", re.I)
rn = re.compile("(.*?)($| [-+][012]\d\d\d$)", re.I)
news_url = 'http://ajax.googleapis.com/ajax/services/search/news?v=1.0&q=%s&key=%s' % \
(quote(key), GOOLE_KEY)
res = urlfetch.fetch(news_url)
if res.status_code == 200:
jj = json.loads(res.content)
if jj.has_key(u"responseStatus") and jj[u"responseStatus"] == 200:
if jj.has_key(u"responseData") and jj[u"responseData"].has_key(u"results"):
for item in jj[u"responseData"][u"results"]:
d = {}
d["title"] = rt.sub("", item[u"title"])
d["url"] = item[u"unescapedUrl"]
d["domain"] = rd.search(item[u"unescapedUrl"]).group(0) + "/"
if item.has_key(u"content"):
d["content"] = rt.sub("", item[u"content"])
d["content"] = d["content"] if len(d["content"]) < 150 else "%s..." % d["content"][:147]
else:
d["content"] = ""
d["image"] = item[u"image"][u"tbUrl"] if item.has_key(u"image") and item[u"image"].has_key(u"tbUrl") else ""
d["publisher"] = item[u"publisher"] if item.has_key("publisher") else ""
if item.has_key("publishedDate"):
d["time"] = item[u"publishedDate"]
rr = rn.match(d["time"])
d["time"] = datetime.strptime(rr.group(1), "%a, %d %b %Y %H:%M:%S")
tz = rr.group(2)
if tz:
d["time"] += timedelta(seconds = (-1 if tz[0] == '-' else 1)* int(tz[1:3])*60 + int(tz[3:]))
news.append(d)
return newsНовости потерпели некоторое изменения, в них появилась дополнительная информация, включая дату публикации (пока даже не знаю зачем).Листинг tasks.py:
#!/usr/bin/env python
# encoding: utf-8
from google.appengine.ext import db
from google.appengine.api import urlfetch
from models import News
from models import Trends
from news import get_news
import re
def trends_update():
trends = []
trend_url = "http://www.google.com/trends/hottrends/atom/hourly"
rl = re.compile("Листинг main.py:
#!/usr/bin/env python
# encoding: utf-8
from bottle import route, run, view, request, redirect, response, post, abort, debug, error
from google.appengine.ext import db
import tasks
from models import News
from models import Trends
debug(True)
@route('/')
@route('')
@view('home')
def home_view():
trends = []
for t in Trends.all().order("-time").fetch(20):
t.news_direct = News.get(t.news)
trends.append(t)
return {"trends" : trends }
@route('/tasks/trends_update')
@route('/tasks/trends_update/')
def trends_update():
tasks.trends_update()
def main():
run(server='gae')
if __name__ == '__main__':
main()Вот, это уже что-то. Напомню, это работающее приложение которое можно увидеть по адресу http://trendstat.appspot.com/.
Комментариев нет:
Отправить комментарий