首页 > 分享 > 揭秘Google Adwords API

揭秘Google Adwords API

搭建一个在线广告营销系统,离不开第三方的支持。而使用第三方提供的API,是一个非常不错的解决方案。

Google提供的Adwords API是一个跨语言的,支持基本所有的主流编程语言。

本文分为四个部分,首先讲解Adwords API是如何做到跨语言的;然后分别讲解Java版本的Client是如何工作的,以及作为开发人员,如何改进和扩展这个API;最后讲解我们在实际的应用中,都遇到了哪些问题。

WebService与AXIS

WebService

使用WebService,是Adwords API能够实现跨语言的原因。简单来说,我们可以这样理解WebService:

客户端(Client)与服务端(Server)之间使用SOAP协议进行通信,这和我们熟悉的HTTP通信非常类似,Client发送一个SOAP请求到Server,Server接受到请求后,开始计算,然后将计算的结果返回给Client。

这是一个SOAP请求:

<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns="https://adwords.google.com/api/adwords/v8">

  <soap:Header>
    <email>loginemail@youraccount.com</email>
    <password>secretpassword</password>
    <useragent>Your User Agent description</useragent>
    <developerToken>_developer_token_here_</developertoken>
    <applicationToken>_application_token_here_</applicationtoken>
  </soap:Header>

  <soap:Body>
    <estimateKeywordList>
      <keywordRequests>
        <type>Broad</type>
        <text>flowers</text>
        <maxCpc>50000</maxCpc>
      </keywordRequests>
    </estimateKeywordList>
  </soap:Body>

</soap:Envelope>

这是一个SOAP应答:

<soapenv:Envelope
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <soapenv:Header>
    <responseTime
        soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
        soapenv:mustUnderstand="0"
        xmlns="https://adwords.google.com/api/adwords/v8">
        10636
    </responseTime>
    <operations
        soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
        soapenv:mustUnderstand="0"
        xmlns="https://adwords.google.com/api/adwords/v8">
        1
    </operations>
    <units
        soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
        soapenv:mustUnderstand="0"
        xmlns="https://adwords.google.com/api/adwords/v8">
        1
    </units>
    <requestId
        soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
        soapenv:mustUnderstand="0"
        xmlns="https://adwords.google.com/api/adwords/v8">
        eb21e6667abb131c117b58086f75abbd
    </requestId>
  </soapenv:Header>

  <soapenv:Body>
    <estimateKeywordListResponse
         xmlns="https://adwords.google.com/api/adwords/v8">
      <estimateKeywordListReturn>
        <avgPosition>2.9376502</avgPosition>
        <cpc>50000</cpc>
        <ctr>0.01992803</ctr>
        <id>-1</id>
        <impressions>62823</impressions>
        <notShownPerDay>139255</notShownPerDay>
      </estimateKeywordListReturn>
    </estimateKeywordListResponse>
  </soapenv:Body>

</soapenv:Envelope>

上面这2个SOAP的示例,就是我们的应用程序利用Adwords API与Google Adwords实际的数据交互情况。

那么,当API非常复杂的时候将会出现什么问题?我们不可能记住所有的方法参数、类定义等等。这个时候,我们需要一个标准的定义文件,用来描述某一个WebService可以提供哪些方法,复杂的数据结果是如何定义的,这个文件就是WSDL(Web Services Definition Language)。我们可以看看一个简单的WSDL定义:

<element name="getName">
  <complexType>
    <sequence>
      <element name="adgroupID" type="xsd:int" />
    </sequence>
  </complexType>
</element>
<element name="getNameResponse">
  <complexType>
    <sequence>
      <element name="getNameReturn" type="xsd:string" />
    </sequence>
  </complexType>
</element>

<wsdl:message name="getNameRequest">
    <wsdl:part element="impl:getName" name="parameters" />
</wsdl:message>

<wsdl:message name="getNameResponse">
    <wsdl:part element="impl:getNameResponse" name="parameters" />
</wsdl:message>

这个WSDL文件定义了这个WebService支持的操作。Adwords API为每一个Service提供了一个WSDL的定义文件,如:https://adwords.google.com/api/adwords/v13/AdService?wsdl

AXIS

如果我们直接在浏览器里面访问https://adwords.google.com/api/adwords/v13/AdService 我们会发现浏览器中出现了这样的字样:

v13/AdService

Hi there, this is an AXIS service!

Perhaps there will be a form for invoking the service here...

这个提示暗示我们:Adwords API的Server端是使用AXIS开发的。

AXIS是Apache下面的一个用于开发WebService应用的框架,具体的使用可以参考它的User Guide。

在使用AXIS开发WebService应用中,有一点非常值得我们注意的:使用WSDL驱动WebService开发,大体流程是这样的:

编写WSDL文件。 使用WSDL2Java,自动生成WSDL中定义的数据代码。 编写每一个方法的实现。 部署服务器。

注意使用WSDL2Java工具根据WSDL文件自动生成的代码,这些代码就是Client与Server之间的协议实现,在两边都会有使用。

Google Adwords API内部构成

Java版本的Adwords API主要有两种类型的发型版本:

adwords-api-X.X.X-loner.tar.gz adwords-api-X.X.X.tar.gz

其中带-loner标识的版本只包含Google发布的代码,而不带-loner标识的版本不仅包含了Google发布的代码,同时包含了Adwords API依赖的所有第三方库,其中当然包括AXIS。

我们打开adwords-api-6.3.0-loner可以看到4个主要的包:

com.google.api.adwords.lib com.google.api.adwords.v13 com.google.api.adwords.v200906 com.google.api.adwords.v200909

其中的2,3,4包都是根据Adwords的WSDL自动生成的代码,用于和Adwords的数据交互,我们开发人员无需关心。

在com.google.api.adwords.lib中,主要包含以下功能: AdWordsServiceLogger:定义了SOAP交互的日志功能。 AdWordsUser,AdWordsVersion,AuthToken,AdWordsService,AdWordsServiceFactory:定义了调用指定WebService对象的实现。 ServiceAccountant,ServiceAccountantRecord,ServiceAccountantManager:定义了记录SOAP日志的策略以及统计Adwords API的使用情况(使用了多少Quota,Response Time)。 AdWordsHttpSender:定义了与Adwords交互的策略,这个类是我们对Adwords API进行改进与扩展的关键。

其中还有一个非常重要的AXIS的Client端配置信息,硬编码在代码中的:

<?xml version='1.0'?>
<deployment name='defaultClientConfig' xmlns='http://xml.apache.org/axis/wsdd/'
    xmlns:java='http://xml.apache.org/axis/wsdd/providers/java'>
    <globalConfiguration>
        <parameter name='disablePrettyXML' value='true' />
    </globalConfiguration>
    <!-- Define the Google Adwords communication strategy -->
    <transport name='http' pivot='java:com.google.api.adwords.lib.AdWordsHttpSender' />
    <transport name='local' pivot='java:org.apache.axis.transport.local.LocalSender' />
    <transport name='java' pivot='java:org.apache.axis.transport.java.JavaSender' />
</deployment>

结合这个配置信息,就非常好理解AdWordsHttpSender的作用了。

AdWordsHttpSender究竟做了哪些事情,这是它的实现代码:

1: public void invoke(MessageContext msgContext) throws AxisFault {

2: super.invoke(msgContext);

3: ServiceAccountantManager.getInstance().recordMessage(msgContext);

4: }

这里的super.invoke(msgContext)调用了AXIS核心的通信功能,完成一次Client与Server之间的SOAP交互,在调用super.invoke(msgContext)之前,msgContext实例中包含SOAP请求的信息;调用super.invoke(msgContext)之后,msgContext实例中就包含了本次调用的SOAP应答的信息。

Client在接收到应答后,又调用了ServiceAccountantManager.getInstance().recordMessage(msgContext),这个函数会将本次SOAP交互的请求与应答记录在日志文件中(如果你的代码中调用了AdWordsServiceLogger.log()),同时解析SOAP应答,将本次请求所花的Quota值与Response Time记录下来。

Google Adwords API的扩展

在上一个部分中,我们了解了Adwords API中自带的AdWordsHttpSender所做的事情:记录SOAP的日志,同时记录每次请求所花的Quota值与Response Time。

这些操作在我们开发和调试阶段还是非常有用的,但是并不适用于实际的生产环境。

直接修改Adwords API的源代码可以解决这个问题,但是这又会引入日后Adwords API升级麻烦的问题。好在Adwords Client端支持一种扩展AdWordsHttpSender的方案:

1 在项目Classpath目录中,加入一个AXIS的Client端配置文件:client-config.wsdd

2 修改文件client-config.wsdd:

<?xml version='1.0'?>
<deployment name='defaultClientConfig' xmlns='http://xml.apache.org/axis/wsdd/'
    xmlns:java='http://xml.apache.org/axis/wsdd/providers/java'>
    <globalConfiguration>
        <parameter name='disablePrettyXML' value='true' />
    </globalConfiguration>
    <!-- Define the Google Adwords communication strategy -->
    <transport name='http' pivot='java:com.cnblogs.gpcuster.MyHTTPSender' />
    <transport name='local' pivot='java:org.apache.axis.transport.local.LocalSender' />
    <transport name='java' pivot='java:org.apache.axis.transport.java.JavaSender' />
</deployment>

3 在项目中创建com.cnblogs.gpcuster.MyHTTPSender文件,仿造AdWordsHttpSender的实现,实现你所希望的交互策略,如:

1: package com.cnblogs.gpcuster;

2: 

3: import org.apache.axis.AxisFault;

4: import org.apache.axis.MessageContext;

5: import org.apache.axis.transport.http.HTTPSender;

6: 

7: /**

8: * {@code AdWordsHttpSender} acts as a custom HTTP transport layer which

9: * allows for access to the {@code MessageContext} before it is processed.

10: * This class is intended to be referenced in the Axis engine as described

11: * by {@link AdWordsServiceFactory}.

12: *

13: * @author gpcuster.cnblogs.com

14: */

15: public class MyHttpSender extends HTTPSender {

16: /**

17: * Default constructor.

18: */

19: public AdWordsHttpSender() {}

20: 

21: /**

22: * @Author: Aaron.Guo

23: *

24: * @Blog:http://gpcuster.cnblogs.com

25:

26: *

27: * @param msgContext the message context to invoke through

28: * {@link HTTPSender} and to record via the

29: * {@link ServiceAccountantManager}

30: */

31: @Override

32: public void invoke(MessageContext msgContext) throws AxisFault {

33: super.invoke(msgContext);

34: // 不记录日志与统计信息

35: //ServiceAccountantManager.getInstance().recordMessage(msgContext);

36: }

37: }

4 在所有使用AdWordsUser实例的时候,一定要设置user.useClasspathClientConfig(true)

这样处理以后,我们在使用Adwords API的时候,就不会再使用默认的交互策略了(不会记录日志与统计交互信息),你可以根据你自己的需要添加相应的需求:如记录日志,失败重试,并发控制等等功能。

但是我们使用自定义的HTTPSender后,并不能完全摆脱Adwords API自带的ServiceAccountantManager,因为AdWordsServiceFactory中每次创建一个Service,都会执行ServiceAccountantManager.getInstance().putService(axisService,user)。

在Adwords API最新的6.4.0的版本中已经默认不使用ServiceAccountantManager的功能了,但是AdWordsServiceFactory中依旧存在每次创建一个Service,都会执行ServiceAccountantManager.getInstance().putService(axisService,user)。这应该是一个Bug,需要官方修复。

实际使用遇到的问题

我们在使用Adwords API的过程中,遇到了各种各样的问题,其中最最棘手的问题如下:

Adwords允许的最大并发访问数量。 大数据量的操作失败概率极高(在官方文档规定的最大数量之内)。 访问不稳定。

通过Adwords API Group的交流,得到的答复如下:

The core engineering team is still actively working on a resolution to
this problem, but at this time I don't have any information on when it
would become available.

总结

Adwords API的使用非常简单(官方文档有非常详细的示例,这里就不详细说明了),但是会出现各个各样的奇怪问题。只有不断实践,多与其他开发人员交流才能用好Adwords API。

希望这篇文章能够给从事Adwords API开发的朋友提供帮助,也欢迎大家一起交流,谈谈遇到的问题与解决的办法。

相关知识

Google的60款开源项目
Google Cloud中的生成式AI:最新进展一览
使用Google reCAPTCHA防止机器注册
2019如何找到利基市场并实现利润最大化?3步就够了!
生日花语API接口
花语箴言API接口
【OpenAI】第一节(OpenAI API)获取OpenAI API KEY的两种方式,开发者必看全方面教程!
Google发布机器学习术语表 (包括简体中文)
REST API 安全设计指南
EOS RPC官方API文档中文版

网址: 揭秘Google Adwords API https://m.huajiangbk.com/newsview830600.html

所属分类:花卉
上一篇: Google Ads
下一篇: 谷歌广告 Google Adwo