用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 httplib,smtplib使用方法
Sep 06 Python
Python设计模式之代理模式实例
Apr 26 Python
Python实用日期时间处理方法汇总
May 09 Python
Python+matplotlib实现计算两个信号的交叉谱密度实例
Jan 08 Python
使用python list 查找所有匹配元素的位置实例
Jun 11 Python
python递归法实现简易连连看小游戏
Mar 25 Python
Python调用C语言的实现
Jul 26 Python
使用OpCode绕过Python沙箱的方法详解
Sep 03 Python
pytorch torch.nn.AdaptiveAvgPool2d()自适应平均池化函数详解
Jan 03 Python
Python使用configparser读取ini配置文件
May 25 Python
Python JSON常用编解码方法代码实例
Sep 05 Python
python实现MD5进行文件去重的示例代码
Jul 09 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
php5.2.0内存管理改进
2007/01/22 PHP
PHP类中的魔术方法(Magic Method)简明总结
2014/07/08 PHP
PHP面向对象程序设计之类与反射API详解
2016/12/02 PHP
正则表达式判断是否存在中文和全角字符和判断包含中文字符串长度
2008/09/27 Javascript
一个轻量级的javascript库 pj介绍
2010/12/19 Javascript
js与jquery正则验证电子邮箱、手机号、邮政编码的方法
2016/07/04 Javascript
JS中动态创建元素的三种方法总结(推荐)
2016/10/20 Javascript
Bootstrap popover用法详解
2016/12/22 Javascript
AngularJS控制器controller给模型数据赋初始值的方法
2017/01/04 Javascript
AngularJS  ng-repeat遍历输出的用法
2017/06/19 Javascript
解决VUE中document.body.scrollTop为0的问题
2018/09/15 Javascript
微信小程序实现富文本图片宽度自适应的方法
2019/01/20 Javascript
新手简单了解vue
2019/05/29 Javascript
JavaScript实现身份证验证代码实例
2019/08/26 Javascript
VUE DEMO之模拟登录个人中心页面之间数据传值实例
2019/10/31 Javascript
微信小程序实现注册登录功能(表单校验、错误提示)
2019/12/10 Javascript
Vue中多元素过渡特效的解决方案
2020/02/05 Javascript
jQuery实现简单飞机大战
2020/07/05 jQuery
JS如何监听div的resize事件详解
2020/12/03 Javascript
Python获取邮件地址的方法
2015/07/10 Python
Python生成器定义与简单用法实例分析
2018/04/30 Python
Python3获取拉勾网招聘信息的方法实例
2019/04/03 Python
Python 实现交换矩阵的行示例
2019/06/26 Python
python爬虫神器Pyppeteer入门及使用
2019/07/13 Python
在Mac中PyCharm配置python Anaconda环境过程图解
2020/03/11 Python
python中return如何写
2020/06/18 Python
BeautifulSoup获取指定class样式的div的实现
2020/12/07 Python
美国最大的万圣节服装网站:HalloweenCostumes.com
2017/10/12 全球购物
美国专业消费电子及摄影器材网站:B&H Photo Video
2019/12/18 全球购物
Nike意大利官网:Nike.com IT
2020/01/19 全球购物
List、Map、Set三个接口,存取元素时,各有什么特点?
2015/09/27 面试题
仓库保管员岗位职责
2013/12/20 职场文书
拾金不昧的表扬信
2014/01/16 职场文书
意外伤害赔偿协议书
2014/09/16 职场文书
2015年学校安全工作总结
2015/04/22 职场文书
css中:last-child不生效的解决方法
2022/08/05 HTML / CSS