Comments

上一篇博客 简单介绍了 zhihu-go 项目的缘起,本篇简单介绍一下关于处理 HTML 的细节。

因为知乎没有开发 API,所以只能通过模拟浏览器操作的方式获取数据,这些数据有两种格式:普通的 HTML 文档和某些 Ajax 接口返回的 JSON(返回的数据实际上也是 HTML)。其实也就是爬虫了,抓取网页,然后提取数据。一般来说从 HTML 文档提取数据有这些做法:正则、XPath、CSS 选择器等。对我来说,正则写起来比较复杂,代码可读性差而且维护起来麻烦;XPath 没有详细了解,不过用起来应该不难,而且 Chrome 浏览器可以直接提取 XPath. zhihu-go 里用的是选择器的方式,使用了 goquery.

goquery 是 “a little like that j-thing, only in Go”,也就是用 jQuery 的方式去操作 DOM. jQuery 大家都很熟,API 也很简单明了。本文不详细介绍 goquery,下面选几个场景(API)讲讲在 zhihu-go 里的应用。

Read on →
Comments

我是知乎重度用户,每天都会花点时间在知乎上面看点东西。有段时间时间线里经常出现爬虫相关的话题,也看到不少直接爬知乎信息的项目;其中一个就是 zhihu-python. 实际上 zhihu-python 不是一个完整的爬虫,正如其文档说明的那样,是一个 API 库,可以基于这些 API 实现一个爬虫应用。zhihu-python 实现了用户、问题、答案、收藏夹相关的信息获取类 API,对于大多数信息获取的目的已经足够。这个项目很受欢迎,然而说实话,代码质量一般,不过思路值得借鉴。

Read on →
Comments

极光推送 是国内最早的第三方消息推送服务,官方提供了多种语言的 SDK 和 REST API,详情见 官方文档。遗憾的是缺少一个 Go 语言版本的 SDK,于是我就动手造轮子,封装了一个 Go 的版本。

实际上这个项目在今年 3 月份就完成了主要的推送相关的接口,在 GitHub 上也收获了几个 star 和 fork. 最近今天突然兴起,又翻出来把 device, tag, alias, report 的一些相关接口也封装完成了。

啰嗦了一大推,差点忘了最重要的东西,下面给出链接:

欢迎使用,并 反馈 issues创建 pull request.

Read on →
Comments

前一篇 Blog 简单介绍了 Celery 及其用法,现在我们看看在 Flask 项目中如何使用 Celery.

注意,这篇 Blog 严重参考了这两篇文章:

  1. Using Celery With Flask: 写了一个完整而且有意义的例子来展示如何在 Flask 中使用 Celery.
  2. Celery and the Flask Application Factory Pattern: 是上文的姊妹篇,描述的是更为真实的场景下,Celery 与 Flask Application Factory 的结合使用。

Read on →
Comments

Introduction

分布式任务队列

Celery 是一个分布式任务队列,下面是 官网 的一段描述:

Celery is an asynchronous task queue/job queue based on distributed message passing. It is focused on real-time operation, but supports scheduling as well.

Celery 简单、灵活、可靠,是一个专注于实时处理的任务队列,同时也支持任务调度。

何为任务队列?

摘自 Celery 官方文档的 中文翻译

任务队列是一种在线程或机器间分发任务的机制。

消息队列的输入是工作的一个单元,称为任务,独立的职程(Worker)进程持续监视队列中是否有需要处理的新任务。

Celery 用消息通信,通常使用中间人(Broker)在客户端和职程间斡旋。这个过程从客户端向队列添加消息开始,之后中间人把消息派送给职程。

Celery 系统可包含多个职程和中间人,以此获得高可用性和横向扩展能力。

Read on →

写 API 的时候,总是会想着如何能提升性能。在一般的 Web 应用里,基本上没什么 CPU 密集型的计算,大部分时间还是消耗在 IO 上面:查询数据库、读写文件、调用第三方 API 等。有些可以异步的操作,比如发送注册邮件、手机验证码等,可以用任务队列来处理。在 Python 的生态里,Celery 就是一个很成熟的解决方案。但是对于很多查询请求,还是需要同步返回的。

如果真的遇到性能问题,正确的做法是先找出性能瓶颈,然后对症下药。比如优化数据库索引、优化数据库查询语句、优化算法和数据结构,加速查询和计算。但是最快的计算就是不算——或只计算一次,也就是把计算(查询)的结果缓存起来,以后相同条件的计算(查询)直接从缓存里获取,而不需要重新计算(查询)。

对于耗时的计算,缓存是一种非常有效的优化手段。但缓存也不是万能的,引入缓存的同时,一些其他问题或需要注意的事情也随之而来,比如数据同步、缓存失效、命中率、分布式等。这里不深入探讨这些问题,仅针对下面这种场景,使用缓存来优化 API 性能:

  • GET 查询
  • 查询很耗时
  • 相同条件、不同时间(或某段时间内)的查询结果是一致的

比如获取静态页面(也可以通过 Nginx 直接返回),查询某些元数据列表(如国家列表、产品分类等)。

Read on →
Comments

在一个 Web 应用里,不管是为了业务逻辑的正确性,还是系统安全性,做好参数(querystring, form, json)验证都是非常必要的。

WTForms 是一个非常好用而且强大的表单校验和渲染的库,提供 Form 基类用于定义表单结构(类似 ORM),内置了丰富的字段类型和校验方法,可以很方便的用来做校验。如果应用需要输出 HTML,集成到模板里也很容易。对于 JSON API 应用,用不到渲染的功能,但是结构化的表单和校验功能依然非常有用。

Read on →
Comments

遵循良好的编码风格,可以有效的提高代码的可读性,降低出错几率和维护难度。在团队开发中,使用(尽量)统一的编码风格,还可以降低沟通成本。

网上有很多版本的编码规范,基本上都是遵循 PEP8 的规范:

除了在编码时主动遵循规范,还有很多有用的工具:

  • IntelliJ IDEA 和 PyCharm 的格式化代码功能
  • Google 开源的 Python 文件格式化工具:github.com/google/yapf
  • pyflakes, pylint 等工具及各种编辑器的插件

本文的内容主要摘自互联网上各种版本的规范,因为公司有些小伙伴代码风格不太好,所以整理了一份算是团队的编码规范。

Read on →
Comments

写完代码测试通过之后,终于松一口气,然后可以愉快的部署上线了。但是问题随之而来:如何部署?或者如何能更自动化的部署?

部署应用是一系列的操作,就环境而言,分为本地和远程服务器,就操作而言,大概包括提交代码、备份代码、更新代码、安装依赖、迁移数据库、重启服务等流程。其中除了提交代码这一步是在本地完成,其余操作都需要在服务器环境执行。

上面的流程当中,有一个很重要的,就是如何同步代码(提交、备份、更新)。就我的经验,了解或用过这些方式:

  • rsync: rsync 是一个文件同步的工具,如果配置好使用起来体验也不错。但是有很多缺点:
    • 配置复杂,命令行参数多
    • 需要在服务器上运行 rsyncd,默认监听 873 端口(可能会有防火墙)
  • scp: scp 底层用的是 SSH 协议,所以只要服务器上运行了 sshd 就可以双向 copy 文件。对于文件传输来说,scp 比 rsync 体验差的地方有:
    • 不能增量更新,每次都是全部传输
    • 不能配置忽略文件(.git 怎么办?)
  • git: 就个人而言,git 是最方便的部署方式了,有版本控制,可以增量更新,可以配置忽略文件,使用简单。实际上只要有可能,都推荐用 git 来发布代码。但问题在于,很多公司的 git 服务器都是在内网的,所以在服务器上无法访问。

很幸运的是,我们有一个公网可以访问的 git 服务器,所以可以用 git 来发布代码。发布完代码后就是后续的一系列操作了,最原始的方式,是登录到服务器,然后一步一步敲命令执行下来。但是如果要频繁部署的话(快速迭代时肯定要经常更新代码),这就变成了繁复的体力劳动,而且容易出错(漏了流程,看花眼了)。于是就想到了脚本,把这些操作写成 shell 脚本,然后执行脚本就好了。这是一个很大的进步,然而仍然存在一个问题:从本地环境到远程环境,需要登录,导致了流程上的阻断。

Fabric 是 Python 编写的一个可以实现自动化部署和系统维护的命令行工具,只需要写一些简单的 Python 代码就能轻松解决上面提到的所有问题。Fabric 底层用的是 SSH 协议,提供了一系列语义清晰的 API 来组合实现部署任务。

Read on →

Supervisor (http://supervisord.org) 是一个用 Python 写的进程管理工具,可以很方便的用来启动、重启、关闭进程(不仅仅是 Python 进程)。除了对单个进程的控制,还可以同时启动、关闭多个进程,比如很不幸的服务器出问题导致所有应用程序都被杀死,此时可以用 supervisor 同时启动所有应用程序而不是一个一个地敲命令启动。

安装

Supervisor 可以运行在 Linux、Mac OS X 上。如前所述,supervisor 是 Python 编写的,所以安装起来也很方便,可以直接用 pip :

sudo pip install supervisor

如果是 Ubuntu 系统,还可以使用 apt-get 安装。

Read on →
getElementsByTagName('BODY')[0]).appendChild(s); }()); getElementsByTagName('BODY')[0]).appendChild(s); }()); getElementsByTagName('BODY')[0]).appendChild(s); }());