Flask创设网址解析应用

作者: 网络编程  发布:2019-09-03

[Python]Flask营造网址解析利用

 

 

剖析央求/响应流程

咱俩将在塑造的深入分析服务多少类似 Google Analytics (更疑似个简化版)

行事流程:

各样要被追踪的页面都会使用 <script> 标签引进二个 JavaScript 文件,那么些文件由大家的行使(举例,放在被深入分析网址的底子模板中) 当有人访谈你的网址的时候,他们的浏览器会奉行那一个 JavaScript 文件 JavaScript 中的代码能够读取当前网页的标题,U途胜L,还大概有任何感兴趣的成分。 最酷的地点是,这几个脚本会动态的创设三个 `` 标签(一般的话是个1*1px的空白图片),这几个标签的 src 属性的 U奥迪Q5L 正式针对大家的剖判应用 当前页面中的新闻搜罗达成并且编码之后就能设置成图片的 src 属性,大家的深入分析服务端就能够接收并深入分析那些新闻分析服务分析达成,把那条音讯存入数据库,然后回到二个1像素的gif图片

下边是互为图:
图片 1

设计思量

因为要在财富有限的 VPS(能够认为是布局比很低的服务器) 上运转, 笔者的博客也不曾多少流浪,所以要轻量,灵活。不管怎么着项指标花色本身都欣赏使用 Flask,那些项目更是如此。 我们将采取 peewee ORM 来积累PV(页面访问数据) 和查询剖判数据。 告诉大家吧,大家的施用不会超越100行代码(包罗注释)。

PV (page view)页面访谈

数据库相关

为了能方面的询问数据,大家将选择关系型数据仓库储存款和储蓄PV数据。 作者选择了 Beck雷DB’s SQLite 接口,因为它是个轻量的放权数据库,也不会用多少内部存款和储蓄器。笔者曾思索过 SQLite, 可是 BerkeleyDB 在出现访谈时候比 SQLite 品质高非常多。 当深入分析利用遭到一些破坏的时候,还是能够保持安静运转。

图片 2

假诺您曾经设置了 Postgresql 或然 MySQL, 那么请自由采纳。

WSGI Server

就算如此有相当多的抉择,不过本身恐怕相比较欣赏使用 gevent。 Gevent 是叁个依据协程的互联网库,使用了 libev 的平地风波机制来促成轻线程(greenlets)。 通过选择 monkey-patching ,没有供给特别的API可能是语法,gevent 会把平常阻塞的 python 程序产生非阻塞的。 Gevent 的 WSGI server,即便十二分基础,不过具有十分高的天性和相当的低的能源消耗。 和数据库一样,假设你选用其余库相比顺手,请自由采取。

创建 virtualenv

大家先给那一个解析应用创设贰个隔绝的条件,安装上 flask, peewee(选取设置gevent).

$ virtualenv analytics
New python executable in analytics/bin/python2
Also creating executable in analytics/bin/python
Installing setuptools, pip...done.

$ cd analytics/
$ source bin/activate
$ pip install flask peewee
...
...
Successfully installed flask peewee Werkzeug Jinja2 itsdangerous markupsafe
Cleaning up...

$ pip install gevent  #  Optional.

一旦您想编写翻译 Python SQLite 驱动来支撑 BerkeleyDB, 检出 playhouse 模块(lib/python2.7/site-packages/playhouse/berkeley_build.sh) 中的 berkeley_build.sh 脚本。 那几个剧本将会下载和编写翻译 BerkeleyDB ,然后再编写翻译pysqlite,详细的经过请看那篇小说。 你也足以跳过这么些手续,直接运用 peewee 的 SqliteDatabase 类。

实现Flask应用

让大家从全体代码框架初始吧。 正如前边冲突的,大家将会创制2个 view,二个用来回到 JavaScript 文件,另二个用来创制1像素的GIF图片。 在 analytics目录(那是小编开荒应用的目录,未有请自行创设),创立 analytics.py 文件,代码在底下列出。 那几个代码包蕴了使用的代码结构,还会有大旨配置。

#coding:utf-8
from base64 import b64decode
import datetime
import json
import os
from urlparse import parse_qsl, urlparse

from flask import Flask, Response, abort, request
from peewee import *
from playhouse.berkeleydb import BerkeleyDatabase  # Optional.


# 1 pixel GIF, base64-encoded.
BEACON = b64decode('R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==')

# Store the database file in the app directory.
APP_DIR = os.path.dirname(__file__)
DATABASE_NAME = os.path.join(APP_DIR, 'analytics.db')
DOMAIN = 'http://127.0.0.1:5000'  # TODO: change me.

# Simple JavaScript which will be included and executed on the client-side.
JAVASCRIPT = '' # TODO: add javascript implementation.

# Flask application settings.
DEBUG = bool(os.environ.get('DEBUG'))
SECRET_KEY = 'secret - change me'  # TODO: change me.

app = Flask(__name__)
app.config.from_object(__name__)

database = BerkeleyDatabase(DATABASE_NAME)  # or SqliteDatabase(DATABASE_NAME)

class PageView(Model):
    # TODO: add model definition.

    class Meta:
        database = database

@app.route('/a.gif')
def analyze():
    # TODO: implement 1pixel gif view.

@app.route('/a.js')
def script():
    # TODO: implement javascript view.

@app.errorhandler(404)
def not_found(e):
    return Response('Not found.')

if __name__ == '__main__':
    database.create_tables([PageView], safe=True)
    app.run()

从浏览器获取音信

大家初阶写搜集顾客端消息的 JavaScript 文件, 首要正是抽出一些页面基本消息

UPRADOL音信,包蕴查询新闻(document.location.href) 页面包车型大巴title (document.title) 页面包车型客车feferring音信,假设局地话 (document.referrer)

上边包车型地铁局地质量也足以领到出来,假设你感兴趣的话(小编:其实可能比列出的多的多,非常是H5),比方:
* cookie信息(document.cookie)
* 文书档案的末段修改时间(document.lastModified)
* 更多

领取了这么些音信之后,大家由此url的询问字符串传给 analyze 那么些view。 为了轻便,那些 js 就要页面加载的时候马上触发,大家把具备的代码封装到叁个无名函数中。 最终动用 encodeU中华VIComponent 方法对富有参数进行转义,确定保证全数参数安全:

(function() {
  var img = new Image,
      url = encodeURIComponent(document.location.href),
      title = encodeURIComponent(document.title),
      ref = encodeURIComponent(document.referrer);
  img.src = '%s/a.gif?url=' + url + '&t=' + title + '&ref=' + ref;
})();

小编们留下Python中的占位符 %s,用来读取 DOMAIN 配置并插入到里面,组成总体的JS代码

在py文件中大家定义一个 JAVASCEvoqueIPT 变量来囤积方面包车型地铁 js代码:

# Simple JavaScript which will be included and executed on the client-side.
JAVASCRIPT = (function(){
    var d=document,i=new Image,e=encodeURIComponent;
    i.src='%s/a.gif?url='+e(d.location.href)+'&ref='+e(d.referrer)+'&t='+e(d.title);
    })().replace('
', '')

在view中如此管理

@app.route('/a.js')
def script():
    return Response(
        app.config['JAVASCRIPT'] % (app.config['DOMAIN']),
        mimetype='text/javascript')

保存PV信息

下面的脚本将会传3个值给 analyze 这些view, 满含页面的U大切诺基L,title,和 referring page。 今后大家来定义二个 PageView 模型来积累那几个数量。

在服务端,大家也得以读取到 新闻报道工作者的IP和呼吁头音信,所以大家也为那几个新闻成立字段,还要加上须要的时辰戳字段。

因为各类浏览器有着不一样的央浼头,每一种页面诉求的询问参数也不尽一样,大家将把他们用 JSON 格式存款和储蓄到 TextField字段中。 若是您选择 Postgresql, 能够用 HStore 可能 native JSON data-type。

下边是 PageView 模型的概念,还定义了二个 JSONField 用来囤积 查询参数和央求头音讯:

class JSONField(TextField):
    Store JSON data in a TextField.
    def python_value(self, value):
        if value is not None:
            return json.loads(value)

    def db_value(self, value):
        if value is not None:
            return json.dumps(value)

class PageView(Model):
    domain = CharField()
    url = TextField()
    timestamp = DateTimeField(default=datetime.datetime.now, index=True)
    title = TextField(default='')
    ip = CharField(default='')
    referrer = TextField(default='')
    headers = JSONField()
    params = JSONField()

    class Meta:
        database = database

先我们给 PageView 加多一个主意,让它能够从呼吁中领取全部须要的值,并存到数据库。 urlparse 模块中带有了广大提取 request 音信的不二等秘书技,大家用那一个点子来得到访谈UQX56L和伸手参数:

class PageView(Model):
    # ... field definitions ...

    @classmethod
    def create_from_request(cls):
        parsed = urlparse(request.args['url'])
        params = dict(parse_qsl(parsed.query))

        return PageView.create(
            domain=parsed.netloc,
            url=parsed.path,
            title=request.args.get('t') or '',
            ip=request.headers.get('X-Forwarded-For', request.remote_addr),
            referrer=request.args.get('ref') or '',
            headers=dict(request.headers),
            params=params)

analyze view 最终一步是回到二个1像素的GIF图片,为了安全起见,大家将检查下 U哈弗L是或不是存在,确认保证不会再数据库插入贰个空荡荡记录。

@app.route('/a.gif')
def analyze():
    if not request.args.get('url'):
        abort(404)

    with database.transaction():
        PageView.create_from_request()

    response = Response(app.config['BEACON'], mimetype='image/gif')
    response.headers['Cache-Control'] = 'private, no-cache'
    return response

开头应用

其不时候假若你想测量检验下行使,能够先在命令行设置下 DEBUG=1 来启动debug模式

(analytics) $ DEBUG=1 python analytics.py
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with reloader

访问 能够看来js文件。 即使本地有任何的web应用,能够把这段js嵌入到它的页面中,测量检验下 分析应用

<script src=http://127.0.0.1:5000/a.js type=text/javascript></script>
为了把应用部署到生产环境,建议使用专用的 WSGI 服务器。我喜欢用 gevent,非常轻量和高性能。你可以修改 analytics.py 文件,使用 gevent 代替原来的 Flask server。 下面是使用 gevent 来运行应用在 5000端口的写法:
if __name__ == '__main__':
   from gevent.wsgi import WSGIServer
   WSGIServer(('', 5000), app).serve_forever()

因为 gevent 是利用 monkey-patching 来促成高并发的,需求在 analytics.py 加上下面一行:

from gevent import monkey; monkey.patch_all()

查询数据

确实以为到到喜欢的是收集了几天数据,查询的时候。这一部分大家将看看哪些从访问的多少中查询出来一些妙不可言的新闻。

下边接纳本人博客的数目,大家将会对近日7天的数码开展局地询问

>>> from analytics import *
>>> import datetime
>>> week_ago = datetime.date.today() - datetime.timedelta(days=7)
>>> base = PageView.select().where(PageView.timestamp >= week_ago)

首先,大家来拜见过去三二十日的PV

>>> base.count()
1133

有多少不相同的IP访谈过自家的网址

>>> base.select(PageView.ip).group_by(PageView.ip).count()
850

访谈最多的11个页面?

print (base
       .select(PageView.title, fn.Count(PageView.id))
       .group_by(PageView.title)
       .order_by(fn.Count(PageView.id).desc())
       .tuples())[:10]

# Prints...
[('Postgresql HStore, JSON data-type and Arrays with Peewee ORM',
  88),
 (Describing Relationships: Django's ManyToMany Through,
  73),
 ('Using python and k-means to find the dominant colors in images',
  66),
 ('SQLite: Small. Fast. Reliable. Choose any three.', 58),
 ('Using python to generate awesome linux desktop themes',
  54),
 (Don't sweat the small stuff - use flask blueprints, 51),
 ('Using SQLite Full-Text Search with Python', 48),
 ('Home', 47),
 ('Blog Entries', 46),
 ('Django Patterns: Model Inheritance', 44)]

4个小时为单位,一仲夏哪些时间拜候的人最多呢?

hour = fn.date_part('hour', PageView.timestamp) / 4
id_count = fn.Count(PageView.id)
print (base
       .select(hour, id_count)
       .group_by(hour)
       .order_by(id_count.desc())
       .tuples())[:]
[(3, 208),
 (2, 201),
 (0, 194),
 (1, 183),
 (4, 178),
 (5, 169)]

依据这个数据,看起来每一日中饭时间访问的人最多,网清晨夜前拜谒的人数最少,总得流量比较平均。

怎么 user-agents 最盛行呢?

from collections import Counter
c = Counter(pv.headers.get('User-Agent') for pv in base)
print c.most_common(5)
[(u'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36',
  81),
 (u'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36',
  70),
 (u'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:32.0) Gecko/20100101 Firefox/32.0',
  50),
 (u'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/7.0.6 Safari/537.78.2',
  37),
 (u'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0',
  37)]

您想要什么数据全看您。 一个有趣的正是查询有个别IP访谈具有页面包车型客车顺系列表。 那也就能够看出大家怎么再你的网址上一页一页的拜谒

inner = base.select(PageView.ip, PageView.url).order_by(PageView.timestamp)
query = (PageView
         .select(PageView.ip, fn.GROUP_CONCAT(PageView.url).alias('urls'))
         .from_(inner.alias('t1'))
         .group_by(PageView.ip)
         .order_by(fn.Count(PageView.url).desc())
print {pv.ip: pv.urls.split(',') for pv in query[:10]}

# Prints something like the following:
{
  u'xxx.xxx.xxx.xxx': [
    u'/blog/peewee-was-baroque-so-i-rewrote-it/',
    u'/blog/peewee-was-baroque-so-i-rewrote-it/',
    u'/blog/',
    u'/blog/postgresql-hstore-json-data-type-and-arrays-with-peewee-orm/',
    u'/blog/search/',
    u'/blog/the-search-for-the-missing-link-what-lies-between-sql-and-django-s-orm-/',
    u'/blog/how-do-you-use-peewee-/'],
  u'xxx.xxx.xxx.xxx': [
    u'/blog/dont-sweat-small-stuff-use-flask-blueprints/',
    u'/',
    u'/blog/',
    u'/blog/migrating-to-sqlite/',
    u'/blog/',
    u'/blog/saturday-morning-hacks-revisiting-the-notes-app/'],
  u'xxx.xxx.xxx.xxx': [
    u'/blog/using-python-to-generate-awesome-linux-desktop-themes/',
    u'/',
    u'/blog/',
    u'/blog/customizing-google-chrome-s-new-tab-page/',
    u'/blog/-wallfix-using-python-to-set-my-wallpaper/',
    u'/blog/simple-botnet-written-python/'],
  # etc...
}

晋级利用的主张

确立二个web接口大概是API来查询pv数据 使用表只怕是临近 Postgresql HStore 来条件伏乞头数据 搜罗客户cookies 追踪客商访谈路线 使用 GeoIP 来分明顾客的地理地点 使用 canvas 指纹来更加好的规定客户的独一性 更加的多更酷的询问来钻探数据

 

解析诉求/响应流程 大家将在构建的分析服务多少类似 谷歌(Google) Analytics (更疑似个简化版) 专业流程: 每一种要被跟...

本文由王中王开奖结果发布于网络编程,转载请注明出处:Flask创设网址解析应用

关键词: