用Python的Django框架编写从Google Adsense中获得报表的应用


Posted in Python onApril 17, 2015

 我完成了更新我们在 Neutron的实时收入统计。在我花了一周的时间完成并且更新了我们的PHP脚本之后,我最终认决定开始使用Python进行抓取,这是值得我去花费我的时间和精力的事情。我建立了一个 Django程序,它可以从不同的来源存储收入统计,我可以用这些去简历视图和用于统计工具的API。

所以在过去的几天里,我写了一个脚本,它可以登入到其他的网页并抓取数据,或者,如果这些网页有 API,可以直接访问 API。我发现了一些事情。

1.requests >httplib2(requests多于httplib2);

2.SOAP很糟糕,但它至少是一个API,Suds使SOAP好一点。我了解到SOAP是我说知道的API中,唯一一个完全基于.net开发的。

3.Beautiful Soup是一个很好的求助对象;

4.我确实十分惊讶,这么多企业能在如此蹩脚的技术中生存下来。
 

我拯救了 Google Adsense,他们将会拥有最好的API,并且因此成为最简单的实现。他有着比我预想的要多的挑战。显然你无法仅仅插入用户名/密码或是APIkey去获取获得进入API的入口,你必须完成整个Oauth2的握手流程。

不幸的是,我发现文档不如我希望过得那样容易查询。我发现了很多死链接。我认为,在这方面Google的人应该做的更好。例如,在他们的up to date developer docs文档中,我发现他们指出了broken link to read more about authentication and authorization。(好的,多么奇怪,我尽快提交了这个问题,这个链接终于开始工作了,我猜你会感谢我。)

所以,这篇博客将尝试记录从Adsense获取报表到我的Django应用的过程。

为了使用Google的API来访问Adsense报表,你需要使用Adsense Management API. 这个API只提供OAuth,所以你需要在浏览器中至少完成一次认证过程,来获取你的证书,然后你可以保存这些证书来进行下一步操作。说实话,我已经听说过OAuth很多次了,但是直到现在,我在实践中仍没有需要来使用它。所以我是边做边学,并欢迎大家留言指出我说的不对的地方。

就我所知,Google对于它的各种产品都拥有一个庞大的API。在研究Adsense之前,你需要在Google API 控制台注册你的应用。我已经成功注册了我的应用。因为我还没有一个可用的URL地址,我现在暂时使用我的开发URL(localhost:8000)。它运作起来似乎正常。并使用提供的这个链接下载JSON文件。

还有,当你管理你的APIs的时候,你需要打开服务选项卡,打开AdSense Management API选项。否则,当你尝试发送请求的时候,你会得到一个错误消息“Access Not Configured”。

Google已经创建了一个Python 客户端库,你可以轻易的通过pip来安装这个库。它还包含一个Django样例项目,这个项目使用这个库实现OAuth2的握手过程。我想,它是使用Django 1.1编写的(因为在写这个项目的时候,Django 1.5才刚刚发布),所以它可能有点过时,但是它可是一个好的开始点。

我的应用很简单。我只需要读取指定日期的收益金额,并保存到我的本地数据库。

我在djaongo项目中创建了一个新的应用,叫做“adsense”。并创建了一个models.py文件来存储认证证书。
 

from django.contrib.auth.models import User
from django.db import models
from oauth2client.django_orm import CredentialsField
 
class Credential(models.Model):
  id = models.ForeignKey(User, primary_key=True)
  credential = CredentialsField()
 
class Revenue(models.Model):
  date = models.DateField(unique=True)
  revenue = models.DecimalField(max_digits=7, decimal_places=2)
 
  def __unicode__(self):
    return '{0} ${1}'.format(self.date, self.revenue)

我把从API控制台下载的JSON文件放到我的应用的文件夹下面,并创建了一个views.py文件

 

import os
 
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.sites.models import Site
from django.http import HttpResponseBadRequest, HttpResponse
from django.http import HttpResponseRedirect
from oauth2client import xsrfutil
from oauth2client.client import flow_from_clientsecrets
from oauth2client.django_orm import Storage
 
from .models import Credential
 
CLIENT_SECRETS = os.path.join(os.path.dirname(__file__), 'client_secrets.json')
 
FLOW = flow_from_clientsecrets(
  CLIENT_SECRETS,
  scope='https://www.googleapis.com/auth/adsense.readonly',
  redirect_uri='http://{0}/adsense/oauth2callback/'.format(
    Site.objects.get_current().domain))
 
@login_required
def index(request):
  storage = Storage(Credential, 'id', request.user, 'credential')
  credential = storage.get()
  if credential is None or credential.invalid is True:
    FLOW.params['state'] = xsrfutil.generate_token(settings.SECRET_KEY,
                            request.user)
    authorize_url = FLOW.step1_get_authorize_url()
    return HttpResponseRedirect(authorize_url)
  else:
    return HttpResponse('Already validated.')
 
@login_required
def auth_return(request):
  if not xsrfutil.validate_token(settings.SECRET_KEY,
                  request.REQUEST['state'], request.user):
    return HttpResponseBadRequest()
  credential = FLOW.step2_exchange(request.REQUEST)
  storage = Storage(Credential, 'id', request.user, 'credential')
  storage.put(credential)
  return HttpResponseRedirect("/")

在 urls.py 文件中我包含了一个链接指向我的应用的url文件

main urls.py:
 
from django.conf.urls import patterns, include, url
from django.contrib import admin
 
admin.autodiscover()
 
urlpatterns = patterns(
  '',
  url(r'^adsense/', include('adsense.urls', namespace='adsense')),
 
  url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
  url(r'^admin/', include(admin.site.urls)),
)

adsense/urls.py:
 
from django.conf.urls import patterns, url
 
urlpatterns = patterns(
  'adsense.views',
  url(r'^$', 'index', name='index'),
  url(r'^oauth2callback/$', 'auth_return', name='auth_return'),
)

最后,创建了一个通过给定日期调用API并获取收益的类。它放在adsense/tasks.py,因为我准备把它当作任务,钩在 Celery/ RabbitMQ之上。
 

import datetime
import httplib2
 
from apiclient.discovery import build
from django.contrib.auth.models import User
from oauth2client.django_orm import Storage
 
from .models import Credential, Revenue
 
TODAY = datetime.date.today()
YESTERDAY = TODAY - datetime.timedelta(days=1)
 
class Scraper(object):
  def get_report(self, start_date=YESTERDAY, end_date=TODAY):
    user = User.objects.get(pk=1)
    storage = Storage(Credential, 'id', user, 'credential')
    credential = storage.get()
    if not credential is None or credential.invalid is False:
      http = httplib2.Http()
      http = credential.authorize(http)
      service = build('adsense', 'v1.2', http=http)
      reports = service.reports()
      report = reports.generate(
        startDate=start_date.strftime('%Y-%m-%d'),
        endDate=end_date.strftime('%Y-%m-%d'),
        dimension='DATE',
        metric='EARNINGS',
      )
      data = report.execute()
      for row in data['rows']:
        date = row[0]
        revenue = row[1]
 
        record = Revenue()
        try:
          r = Revenue.objects.get(date=date)
          pk = r.id
        except Revenue.DoesNotExist:
          pk = None
        record.id = pk
        record.date = date
        record.revenue = revenue
        record.save()

为了让它能工作起来,我在浏览器打开http://localhost:8000/adsense/。这时候会要求我登录Google帐号。我为我的应用授权来访问Adsense。然后,认证证书就会保存在我的本地数据库,然后我可以调用Scraper get_report() 方法。祝贺我吧!。它能顺利工作了。

Python 相关文章推荐
Python内置函数bin() oct()等实现进制转换
Dec 30 Python
python中urllib模块用法实例详解
Nov 19 Python
在Mac OS上部署Nginx和FastCGI以及Flask框架的教程
May 02 Python
Python3利用Dlib19.7实现摄像头人脸识别的方法
May 11 Python
python3判断url链接是否为404的方法
Aug 10 Python
python+opencv打开摄像头,保存视频、拍照功能的实现方法
Jan 08 Python
详解Python 爬取13个旅游城市,告诉你五一大家最爱去哪玩?
May 07 Python
django将数组传递给前台模板的方法
Aug 06 Python
使用Python paramiko模块利用多线程实现ssh并发执行操作
Dec 05 Python
使用pyshp包进行shapefile文件修改的例子
Dec 06 Python
使用keras实现BiLSTM+CNN+CRF文字标记NER
Jun 29 Python
用python计算文件的MD5值
Dec 23 Python
在Docker上开始部署Python应用的教程
Apr 17 #Python
使用Python装饰器在Django框架下去除冗余代码的教程
Apr 16 #Python
在服务器端实现无间断部署Python应用的教程
Apr 16 #Python
使用Protocol Buffers的C语言拓展提速Python程序的示例
Apr 16 #Python
使用Python编写一个模仿CPU工作的程序
Apr 16 #Python
利用Python中的mock库对Python代码进行模拟测试
Apr 16 #Python
使用Python脚本来控制Windows Azure的简单教程
Apr 16 #Python
You might like
joomla组件开发入门教程
2016/05/04 PHP
php 中phar包的使用教程详解
2018/10/26 PHP
PDO::getAvailableDrivers讲解
2019/01/28 PHP
仅IE9/10同时支持script元素的onload和onreadystatechange事件分析
2011/04/27 Javascript
获取元素距离浏览器周边的位置的方法getBoundingClientRect
2013/04/17 Javascript
简单选项卡 js和jquery制作方法分享
2014/02/26 Javascript
jquery 操作两个select实现值之间的互相传递
2014/03/07 Javascript
jquery用ajax方式从后台获取json数据后如何将内容填充到下拉列表
2015/08/26 Javascript
jQuery焦点图插件SaySlide
2015/12/21 Javascript
AngularJS验证信息框架的封装插件用法【w5cValidator扩展插件】
2016/11/03 Javascript
Angular4学习笔记之新建项目的方法
2017/07/18 Javascript
详解使用vue-cli脚手架初始化Vue项目下的项目结构
2018/03/08 Javascript
微信小程序实现美团菜单
2018/06/06 Javascript
解决vue v-for 遍历循环时key值报错的问题
2018/09/06 Javascript
解决echarts的多个折现数据出现坐标和值对不上的问题
2018/12/28 Javascript
Node.js API详解之 repl模块用法实例分析
2020/05/25 Javascript
IDEA配置jQuery, $符号不再显示黄色波浪线的问题
2020/10/09 jQuery
微信小程序实现滚动Tab选项卡
2020/11/16 Javascript
vue 插槽简介及使用示例
2020/11/19 Vue.js
[03:17]2016完美“圣”典风云人物:冷冷专访
2016/12/08 DOTA
用python代码做configure文件
2014/07/20 Python
Python中__call__用法实例
2014/08/29 Python
跟老齐学Python之有点简约的元组
2014/09/24 Python
Python Web框架Flask中使用百度云存储BCS实例
2015/02/08 Python
Python解析json文件相关知识学习
2016/03/01 Python
python爬取盘搜的有效链接实现代码
2019/07/20 Python
Python K最近邻从原理到实现的方法
2019/08/15 Python
css3 中translate和transition的使用方法
2020/03/26 HTML / CSS
英国在线药房和在线医生:LloydsPharmacy
2019/10/21 全球购物
暑期社会实践方案
2014/02/05 职场文书
大学毕业感言50字
2014/02/07 职场文书
元旦联欢会感言
2014/03/04 职场文书
三年级小学生评语
2014/04/22 职场文书
国际商务专业求职信
2014/07/15 职场文书
国庆促销活动总结
2014/08/29 职场文书
幽默口才训练经典句子(48句)
2019/08/19 职场文书