以前、Google Analytics V4 API(Java) URL ごとのpageview を取得する | Monotalkで、Google Analytics V4 API
について書きました。
Search Consoleについても、Search Console APIs | Google Developers というAPI があり、java の client があることを知ったので、今回はこちらを使ってみた結果を記載します。
参考
使用可能な API について
Google APIs Explorer から取得した Search Console API v3
の API のリストです
検索パフォーマンスデータの取得、sitemap の送信 / 取得 / 削除 、 site 登録 、 クロールエラーURL の 編集が可能です。
API名 | 説明 |
---|---|
webmasters.searchanalytics.query | 検索アナリティクスのデータを取得する |
webmasters.sitemaps.delete | Search Console に 送信した sitemap を 削除する |
webmasters.sitemaps.get | Search Console に 送信した sitemap を 取得する |
webmasters.sitemaps.list | Search Console に 送信した sitemap の list を取得する。 |
webmasters.sitemaps.submit | Search Console に sitemap を送信する |
webmasters.sites.add | Search Console に site を追加する |
webmasters.sites.delete | Search Console に 登録した site を削除する |
webmasters.sites.get | Search Console に 登録した site の情報を取得する |
webmasters.sites.list | Search Console に 登録した site の情報の list を取得する |
webmasters.urlcrawlerrorscounts.query | エラーカテゴリとプラットフォームごとのURLクロールエラー数の時系列を取得する |
webmasters.urlcrawlerrorssamples.get | サイトのサンプルURLのクロールエラーの詳細を取得する |
webmasters.urlcrawlerrorssamples.list | 指定されたクロールエラーカテゴリとプラットフォームのサイトのサンプルURLを一覧表示する |
webmasters.urlcrawlerrorssamples.markAsFixed | 提供されたサイトのサンプルURLを修正済みとしてマークし、サンプルリストから削除する |
Google Search Console API を使用するメリット
触った限り、Google Serach Console の画面から操作するのに比べて以下のようなメリットがあると思いました。
-
Dimension を複数設定できる
Dimension の要素として、画面上からだと、クエリ
、ページ
、国
、デバイス
、日付
、検索タイプ
が指定可能ですが、1つしか指定できません。
API 経由だと、検索タイプ
以外の Dimension を複数指定して検索することができます。 -
スケジューラに設定して、バックアップを自動化する
Google Search Console は、過去3月分しかデータを参照できないため、
定期的に、データをExportしておく必要があります。
スケジューラから、APIを起動することで、データのバックアップの自動化ができます。 -
サイト管理作業の自動化
SiteMap登録、サイト削除などのいくつかの更新オペレーションを行うAPIがあります。
大量に登録/削除を実施する場合は、このあたりを使用することで、効率化できそうに思います。
ただ、サイトの分析データのバックアップだけであれば、Search Analytics for Sheets - Google スプレッドシート アドオン を使うのが簡単でいいと思います。
サイト管理系のオペレーションを行う、または、APIの結果から独自の指標を計算して出力する必要がある場合、各言語のクライアントを使用することになります。1
[1].この記事を書いておいてなのですが、個人的に利用する分には、Search Analytics for Sheets
で事足りそうです。
サービスアカウントの作成と、キーの発行
API の認証には OAuth2 ではなくて、 サービスアカウントの Json キーを使用して、認証を行いました。
手順
以下の記事がわかりやすいです。
Google Search Console に読み替えれば設定できるかと思います。
[API] Google APIを使う際に、APIを有効化して認証キーを取得する方法 - YoheiM .NET
作成したアカウントをGoogle Search Console に追加する。
記事に記載がないところの補足です。
-
Google Search Console Top の対象サイト、プロパティの管理から、
ユーザーのを追加/削除
をクリック
-
ユーザーとプロパティ所有者の一覧に遷移、
新しいユーザーの追加
をクリック
-
作成したアカウントのメールアドレスを入力し、追加をクリック。
権限はフルでなくても参照はできるかと思います。
-
ユーザーとプロパティ所有者の一覧に戻る。追加したアカウントが一覧にも追加される。
これで、プログラム実行の事前準備は終わりです。
gradle 、maven にライブラリ依存関係を追加
google-api-services-webmasters
というライブラリと、
google-api-client
が必要になります。
-
maven
<!-- https://mvnrepository.com/artifact/com.google.api-client/google-api-client --> <dependency> <groupId>com.google.api-client</groupId> <artifactId>google-api-client</artifactId> <version>1.22.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.google.apis/google-api-services-webmasters --> <dependency> <groupId>com.google.apis</groupId> <artifactId>google-api-services-webmasters</artifactId> <version>v3-rev22-1.22.0</version> </dependency>
-
gradle
compile group: 'com.google.api-client', name: 'google-api-client', version: '1.22.0' compile 'com.google.apis:google-api-services-webmasters:v3-rev22-1.22.0'
サンプル実装
SitesExample.java
Google Search Console のサイトの一覧情報するプログラムです。
Webmasters.Sites.List#execute()
で取得しています。
Quickstart: Run a Search Console App in Java | Search Console API | Google Developers と実装上やっていることは同じです。
認証はサービスアカウントのJSONキーを使って認証しているので、
GoogleCredential.fromStream(new FileInputStream(KEY_FILE_LOCATION)).createScoped(Collections.singleton(WebmastersScopes.WEBMASTERS));
の、KEY_FILE_LOCATION
にJSONキーのファイルパスを指定しています。
動かす場合は、private static final String KEY_FILE_LOCATION = "{api_key_file_path}";
をダウンロードした、JSONキーのファイルパスに変更してください。
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.webmasters.Webmasters;
import com.google.api.services.webmasters.WebmastersScopes;
import com.google.api.services.webmasters.model.SitesListResponse;
import com.google.api.services.webmasters.model.WmxSite;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;
import static java.lang.System.out;
/**
* SitesExample
*/
public class SitesExample {
private static final String KEY_FILE_LOCATION = "{api_key_file_path}";
/**
* main method
*
* @param args
*/
public static void main(String[] args) {
Webmasters webmasters = buildWebmasters();
try {
Webmasters.Sites.List request = webmasters.sites().list();
SitesListResponse siteList = request.execute();
out.println("siteList#toPrettyString() START>>>");
out.println(siteList.toPrettyString());
out.println("<<<END");
out.println("siteList#getSiteEntry(); START>>>");
List<WmxSite> wmxSites = siteList.getSiteEntry();
int i = 0;
for (WmxSite wmxSite : wmxSites) {
out.println("--------wmxSite:elem" + (++i) + "--------");
out.println("permissionLevel:" + wmxSite.getPermissionLevel());
out.println("siteUrl:" + wmxSite.getSiteUrl());
}
out.println("<<<END");
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static Webmasters buildWebmasters() {
HttpTransport httpTransport = null;
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
}
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential credential = null;
try {
credential = GoogleCredential.fromStream(new FileInputStream(KEY_FILE_LOCATION)).createScoped(Collections.singleton(WebmastersScopes.WEBMASTERS));
} catch (IOException e) {
throw new IllegalStateException(e);
}
// Create a new authorized API client
Webmasters webmasters = new Webmasters.Builder(httpTransport, jsonFactory, credential).setApplicationName("Search Console Cli").build();
return webmasters;
}
}
SiteMapsExample.java
以下、登録したSiteMap の一覧情報を取得するサンプルになります。
Webmasters.Sitemaps.List#execute()
でサイトマップの一覧は取得可能です。
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.webmasters.Webmasters;
import com.google.api.services.webmasters.WebmastersScopes;
import com.google.api.services.webmasters.model.SitemapsListResponse;
import com.google.api.services.webmasters.model.WmxSitemap;
import com.google.api.services.webmasters.model.WmxSitemapContent;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;
import static java.lang.System.out;
/**
* SiteMapsExample
*/
public class SiteMapsExample {
private static final String KEY_FILE_LOCATION = "{api_key_file_path}";
/**
* main method
*
* @param args
*/
public static void main(String[] args) {
Webmasters webmasters = buildWebmasters();
try {
Webmasters.Sitemaps.List siteMaps = webmasters.sitemaps().list("https://www.monotalk.xyz");
SitemapsListResponse response = siteMaps.execute();
out.print("response#toPrettyString() START>>>");
out.print(response.toPrettyString());
out.print("<<<END");
List<WmxSitemap> wmxSitemaps = response.getSitemap();
out.println("response#getSitemap(); START>>>");
int i = 0;
for (WmxSitemap wmxSitemap : wmxSitemaps) {
out.println("--------wmxSitemap:elem" + (++i) + "--------");
out.println("path:" + wmxSitemap.getPath());
out.println("type:" + wmxSitemap.getType());
out.println("isPending:" + wmxSitemap.getIsPending());
out.println("isSitemapsIndex:" + wmxSitemap.getIsSitemapsIndex());
out.println("lastDownloaded:" + wmxSitemap.getLastDownloaded());
out.println("lastSubmitted:" + wmxSitemap.getLastSubmitted());
List<WmxSitemapContent> wmxSitemapContents = wmxSitemap.getContents();
int j = 0;
for (WmxSitemapContent wmxSitemapContent : wmxSitemapContents) {
out.println("--------wmxSitemapContent:elem" + (++j) + "---");
out.println("wmxSitemapContent.indexed:" + wmxSitemapContent.getIndexed());
out.println("wmxSitemapContent.submitted:" + wmxSitemapContent.getSubmitted());
out.println("wmxSitemapContent.type:" + wmxSitemapContent.getType());
}
}
out.println("<<<END");
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static Webmasters buildWebmasters() {
HttpTransport httpTransport = null;
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
}
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential credential = null;
try {
credential = GoogleCredential.fromStream(new FileInputStream(KEY_FILE_LOCATION)).createScoped(Collections.singleton(WebmastersScopes.WEBMASTERS));
} catch (IOException e) {
throw new IllegalStateException(e);
}
// Create a new authorized API client
Webmasters webmasters = new Webmasters.Builder(httpTransport, jsonFactory, credential).setApplicationName("Search Console Cli").build();
return webmasters;
}
}
SearchAnalyticsExample.java
サイト分析結果取得のサンプルになります。
Webmasters#searchanalytics()#query()#execute()
でクエリを発行して結果を取得しています。
dimentions として、date
を指定していますが、ドキュメントには指定可能な記載がありませんでした。
試しに指定してみたところ、ちゃんとグルーピングされて取得できたので、指定可能と判断して指定しています。
query#setAggregationType()
については、挙動がよくわからず、指定せずにコメントアウトしています。
また、query.setDimensionFilterGroups(apiDimensionFilterGroups)
で設定しているフィルターの条件は、
「page の、url に “java”を含み、且つ、page の、url に “codec”を含む」 FilterGroupはand でのみ設定可能なようで、
FilterGroup を2つ設定しても、Filterを2つ設定しても挙動は変わりませんでした。
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.webmasters.Webmasters;
import com.google.api.services.webmasters.WebmastersScopes;
import com.google.api.services.webmasters.model.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.lang.System.out;
/**
* SearchAnalyticsExample
*/
public class SearchAnalyticsExample {
private static final String KEY_FILE_LOCATION = "{api_key_file_path}";
/**
* main method
*
* @param args
*/
public static void main(String[] args) {
Webmasters webmasters = buildWebmasters();
try {
SearchAnalyticsQueryRequest query = new SearchAnalyticsQueryRequest();
query.setStartDate("2016-07-02");
query.setEndDate("2017-05-02");
query.setRowLimit(5000);
query.setStartRow(0);
query.setSearchType("web");
List<String> dimentions = new ArrayList<String>();
dimentions.add("page");
dimentions.add("query");
dimentions.add("date");
dimentions.add("device");
dimentions.add("country");
query.setDimensions(dimentions);
// ----------------------------
// AgregationType
// -----------------
// query.setAggregationType("auto");
// query.setAggregationType("byPage");
// query.setAggregationType("byProperty");
List<ApiDimensionFilterGroup> apiDimensionFilterGroups = getApiDimensionFilterGroups();
query.setDimensionFilterGroups(apiDimensionFilterGroups);
SearchAnalyticsQueryResponse searchAnalyticsQueryResponse = webmasters.searchanalytics().query("https://www.monotalk.xyz", query).execute();
out.println("searchAnalyticsQueryResponse#.toPrettyString() START>>>");
out.println(searchAnalyticsQueryResponse.toPrettyString());
out.println("<<<END");
for (ApiDataRow row : searchAnalyticsQueryResponse.getRows()) {
out.println(row.toPrettyString());
}
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static List<ApiDimensionFilterGroup> getApiDimensionFilterGroups() {
// page の、url に "java"を含み、且つ、page の、url に "codec"を含む
// ページのみに絞り込み
ApiDimensionFilter javaFilter = new ApiDimensionFilter();
javaFilter.setDimension("page");
javaFilter.setExpression("java");
javaFilter.setOperator("contains");
ArrayList<ApiDimensionFilter> javaFilters = new ArrayList<>();
javaFilters.add(javaFilter);
ApiDimensionFilterGroup apiDimensionJavaFilterGroup = new ApiDimensionFilterGroup();
apiDimensionJavaFilterGroup.setFilters(javaFilters);
apiDimensionJavaFilterGroup.setGroupType("and");
ApiDimensionFilter codecFilter = new ApiDimensionFilter();
codecFilter.setDimension("page");
codecFilter.setExpression("codec");
codecFilter.setOperator("contains");
ArrayList<ApiDimensionFilter> pythonFilters = new ArrayList<>();
pythonFilters.add(codecFilter);
ApiDimensionFilterGroup apiDimensionPythonFilterGroup = new ApiDimensionFilterGroup();
apiDimensionPythonFilterGroup.setFilters(pythonFilters);
apiDimensionPythonFilterGroup.setGroupType("and");
List<ApiDimensionFilterGroup> apiDimensionFilterGroups = new ArrayList<>();
apiDimensionFilterGroups.add(apiDimensionJavaFilterGroup);
apiDimensionFilterGroups.add(apiDimensionPythonFilterGroup);
return apiDimensionFilterGroups;
}
private static Webmasters buildWebmasters() {
HttpTransport httpTransport = null;
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
}
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential credential = null;
try {
credential = GoogleCredential.fromStream(new FileInputStream(KEY_FILE_LOCATION)).createScoped(Collections.singleton(WebmastersScopes.WEBMASTERS));
} catch (IOException e) {
throw new IllegalStateException(e);
}
// Create a new authorized API client
Webmasters webmasters = new Webmasters.Builder(httpTransport, jsonFactory, credential).setApplicationName("Search Console Cli").build();
return webmasters;
}
}
UrlCrawlErrorsCountsExample.java
クロールエラーのサマリーを返す、APIのサンプルです。
Webmasters.Urlcrawlerrorscounts#query()
で、サマリーを取得しています。
エラーチェック用途のAPIでしょうか..?
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.webmasters.Webmasters;
import com.google.api.services.webmasters.WebmastersScopes;
import com.google.api.services.webmasters.model.UrlCrawlErrorCount;
import com.google.api.services.webmasters.model.UrlCrawlErrorCountsPerType;
import com.google.api.services.webmasters.model.UrlCrawlErrorsCountsQueryResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;
import static java.lang.System.out;
/**
* UrlCrawlErrorsCountsExample
*/
public class UrlCrawlErrorsCountsExample {
private static final String KEY_FILE_LOCATION = "{api_key_file_path}";
/**
* main method
*
* @param args
*/
public static void main(String[] args) {
Webmasters webmasters = buildWebmasters();
try {
Webmasters.Urlcrawlerrorscounts.Query request = webmasters.urlcrawlerrorscounts().query("https://www.monotalk.xyz");
UrlCrawlErrorsCountsQueryResponse response = request.execute();
out.println("response#toPrettyString() START>>>");
out.println(response.toPrettyString());
out.println("<<<END");
out.println("responset#getCountPerTypes(); START>>>");
List<UrlCrawlErrorCountsPerType> urlCrawlErrorCountsPerTypes = response.getCountPerTypes();
int i = 0;
for (UrlCrawlErrorCountsPerType urlCrawlErrorCountsPerType : urlCrawlErrorCountsPerTypes) {
out.println("--------urlCrawlErrorCountsPerType:elem" + (++i) + "--------");
out.println("category:" + urlCrawlErrorCountsPerType.getCategory());
out.println("platform:" + urlCrawlErrorCountsPerType.getPlatform());
java.util.List<UrlCrawlErrorCount> urlCrawlErrorCounts = urlCrawlErrorCountsPerType.getEntries();
int j = 0;
for (UrlCrawlErrorCount urlCrawlErrorCount : urlCrawlErrorCounts) {
out.println("----urlCrawlErrorCount:elem" + (++j) + "--------");
out.println("count:" + urlCrawlErrorCount.getCount());
out.println("timestamp:" + urlCrawlErrorCount.getTimestamp());
}
}
out.println("<<<END");
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static Webmasters buildWebmasters() {
HttpTransport httpTransport = null;
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
}
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential credential = null;
try {
credential = GoogleCredential.fromStream(new FileInputStream(KEY_FILE_LOCATION)).createScoped(Collections.singleton(WebmastersScopes.WEBMASTERS));
} catch (IOException e) {
throw new IllegalStateException(e);
}
// Create a new authorized API client
Webmasters webmasters = new Webmasters.Builder(httpTransport, jsonFactory, credential).setApplicationName("Search Console Cli").build();
return webmasters;
}
}
UrlCrawlErrorsSamplesExample.java
こちらは、サマリーではなく、クロールエラーとなったURLの、
詳細情報が取得できます。
Webmasters.Urlcrawlerrorssamples#list()
で引数には、エラーのカテゴリと検索タイプの指定が、必須になります。
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.webmasters.Webmasters;
import com.google.api.services.webmasters.WebmastersScopes;
import com.google.api.services.webmasters.model.UrlCrawlErrorsSample;
import com.google.api.services.webmasters.model.UrlCrawlErrorsSamplesListResponse;
import com.google.api.services.webmasters.model.UrlSampleDetails;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;
import static java.lang.System.out;
/**
* UrlCrawlErrorsSamplesExample
*/
public class UrlCrawlErrorsSamplesExample {
private static final String KEY_FILE_LOCATION = "{api_key_file_path}";
/**
* main method
*
* @param args
*/
public static void main(String[] args) {
Webmasters webmasters = buildWebmasters();
try {
Webmasters.Urlcrawlerrorssamples.List request = webmasters.urlcrawlerrorssamples().list("https://www.monotalk.xyz", "notFound", "web");
UrlCrawlErrorsSamplesListResponse response = request.execute();
out.println("response#toPrettyString() START>>>");
out.println(response.toPrettyString());
out.println("<<<END");
out.println("responset#getUrlCrawlErrorSample(); START>>>");
List<UrlCrawlErrorsSample> urlCrawlErrorSamples = response.getUrlCrawlErrorSample();
int i = 0;
for (UrlCrawlErrorsSample urlCrawlErrorsample : urlCrawlErrorSamples) {
out.println("--------urlCrawlErrorsample:elem" + (++i) + "--------");
out.println("pageUrl:" + urlCrawlErrorsample.getPageUrl());
out.println("firstDetected:" + urlCrawlErrorsample.getFirstDetected());
out.println("lastCrawled:" + urlCrawlErrorsample.getLastCrawled());
out.println("responseCode:" + urlCrawlErrorsample.getResponseCode());
UrlSampleDetails userDetails = urlCrawlErrorsample.getUrlDetails();
}
out.println("<<<END");
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static Webmasters buildWebmasters() {
HttpTransport httpTransport = null;
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
}
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential credential = null;
try {
credential = GoogleCredential.fromStream(new FileInputStream(KEY_FILE_LOCATION)).createScoped(Collections.singleton(WebmastersScopes.WEBMASTERS));
} catch (IOException e) {
throw new IllegalStateException(e);
}
// Create a new authorized API client
Webmasters webmasters = new Webmasters.Builder(httpTransport, jsonFactory, credential).setApplicationName("Search Console Cli").build();
return webmasters;
}
}
後半、ちょっと駆け足になりました。
そのうち補足でもしようかと思います。
以上です。
コメント