Google AdSenseのレポートをPythonで取得する

# やること
僭越ながら、Google AｄSenseで広告収益を得ているのですが、毎日いくら稼げたかな〜と[Google AdSense](https://www.google.com/intl/ja_jp/adsense/start/)にログインして確認していました。
これをプログラムで取得して、毎日Slackなどに投稿することができれば面白いなと考え、[AdSense Management API](https://developers.google.com/adsense/management?hl=ja)を触り始めました。
本記事では、PythonでAdSense Management APIを使用して、Google AdSenseのレポートを取得する手順を記載したいと思います。
ハマりにハマったので、備忘録として残そうと考えたのも書くきっかけです。

# 事前確認
手順に入る前に、まず現状を共有しておきます。
* Google AdSenseのアカウント作成は完了しています。
* Google AdSenseで収益を得ていて、レポートを作成できる状態です。

# 手順
## Google Cloud
### プロジェクトの作成
[Google Cloud Platform](https://console.cloud.google.com/?hl=JA)にログインします。
新しいプロジェクトを作成します。ここでは「My Project 77498」としました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/7838da45-cafe-ab09-a9f0-1f9c6fba8626.png">

### AdSense Management APIの有効化
「APIとサービス」から「ライブラリ」をクリックします。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/e95d3273-8cd6-798b-1f23-21b9a2887b90.png">

"Google AdSense"というワードで検索すると2件ヒットしました。「AdSense Management API」をクリックします。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/161a33f8-3bf9-8e89-073b-4b06fab1461f.png">

「有効にする」をクリックして有効化します。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/0f787ee3-dd5e-8cdb-6568-22b50a6a9383.png">

### OAuth同意画面の作成
「OAuth同意画面」をクリックして、OAuth同意画面を作成していきます。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/14385566-fdba-1102-e72e-02d86828b13b.png">

「外部」にチェックを入れて「作成」をクリックしました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/558f513c-0218-42af-88e8-5bbff93591c6.png">

「アプリ名」を入力します。ここでは「My AdSense App」としました。
「ユーザーサポートメール」をプルダウンから選びます。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/14b8fb16-3aa6-78cb-dff8-dbd084166f32.png">

「デベロッパーの連絡先情報」のメールアドレスを入力して、「保存して次へ」をクリックしました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/d4d22d8f-1d6c-ecda-a6c3-fda5c811ad31.png">

「スコープを追加または削除」をクリックして、スコープを追加します。
ここでは、「Google API サービスの設定の管理」の「Service Management API」を追加しました。
「保存して次へ」をクリックしました。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/1d473f90-43aa-7d8f-6b1c-ae6874d55eaa.png">

テストユーザーにはテストに使用するGmailのメールアドレスを入力しました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/c92f2d6c-53d7-859a-0827-737fc8286c3a.png">

### OAuthクライアントIDの作成
「認証情報」から「認証情報の作成」をクリックし、「OAuthクライアントID」を選択します。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/07eccfa8-f30e-bac2-e184-4fbb81765fd9.png">

「アプリケーションの種類」は「ウェブアプリケーション」を選択して、いったんこのまま作成しました。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/2cd1150a-37ed-2d6c-e587-8c58bbd5a765.png">

JSONの認証情報ファイルをダウンロードして、任意のディレクトリに保存しておきます。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/3cd40871-1bba-2daa-eced-9435fe85afc3.png">


## プログラム
### コードのダウンロードと認証情報ファイル配置
公式が用意している[googleads-adsense-examples](https://github.com/googleads/googleads-adsense-examples)のコードをダウンロードします。

ダウンロードしたものの中で「python」ディレクトリをVS Codeなどで開きます。

この中に、先ほどダウンロードしたJSONの認証情報ファイルを、「client_secrets.json」という名前で保存します。デフォルトのものはバックアップを取得しました。

ディレクトリ構成は、以下のようになっているはずです。

```text
v2--
   |--python
        |--adsense_util.py
        |--client_secrets.json.bk
        |--client_secrets.json ←先ほどダウンロードした認証情報ファイル
        |--generate_report.py
        |--get_account_tree.py
        |--get_all_accounts.py
        |--get_all_ad_clients.py
        |--get_all_ad_units_for_custom_channel.py
        |--get_all_ad_units.py
        |--get_all_alerts.py
        |--get_all_custom_channels_for_ad_unit.py
        |--get_all_custom_channels.py
        |--get_all_payments.py
        |--get_all_saved_reports.py
        |--get_all_url_channels.py
        |--README.md

```

### ライブラリのインストール
python仮想環境を用意しました。
```text
python % python -m venv .venv
python % ll -a
total 128
drwxrwxr-x@ 19 atsushi  staff   608  2  7 11:30 .
drwxrwxr-x@  8 atsushi  staff   256  2  7 11:15 ..
drwxr-xr-x   6 atsushi  staff   192  2  7 11:30 .venv
-rw-rw-r--@  1 atsushi  staff  1775  5 12  2022 README.md
-rw-rw-r--@  1 atsushi  staff  3378  5 12  2022 adsense_util.py
-rw-r--r--@  1 atsushi  staff   680  2  6 14:12 client_secrets.json
-rw-rw-r--@  1 atsushi  staff   273  5 12  2022 client_secrets.json.bk
-rw-rw-r--@  1 atsushi  staff  2890  5 12  2022 generate_report.py
-rw-rw-r--@  1 atsushi  staff  2065  5 12  2022 get_account_tree.py
-rw-rw-r--@  1 atsushi  staff  1811  5 12  2022 get_all_accounts.py
-rw-rw-r--@  1 atsushi  staff  2182  5 12  2022 get_all_ad_clients.py
-rw-rw-r--@  1 atsushi  staff  2551  5 12  2022 get_all_ad_units.py
-rw-rw-r--@  1 atsushi  staff  2811  5 12  2022 get_all_ad_units_for_custom_channel.py
-rw-rw-r--@  1 atsushi  staff  1944  5 12  2022 get_all_alerts.py
-rw-rw-r--@  1 atsushi  staff  2617  5 12  2022 get_all_custom_channels.py
-rw-rw-r--@  1 atsushi  staff  2703  5 12  2022 get_all_custom_channels_for_ad_unit.py
-rw-rw-r--@  1 atsushi  staff  2169  5 12  2022 get_all_payments.py
-rw-rw-r--@  1 atsushi  staff  2121  5 12  2022 get_all_saved_reports.py
-rw-rw-r--@  1 atsushi  staff  2573  5 12  2022 get_all_url_channels.py
```

[公式](https://github.com/googleads/googleads-adsense-examples/blob/main/v2/python/README.md)にある通り、必要ライブラリをインストールします。
```text
python % source .venv/bin/activate
(.venv) python % 
(.venv) python % pip install google-api-python-client
Collecting google-api-python-client
  Using cached google_api_python_client-2.76.0-py2.py3-none-any.whl (11.0 MB)
Collecting google-auth<3.0.0dev,>=1.19.0
  Using cached google_auth-2.16.0-py2.py3-none-any.whl (177 kB)
Collecting httplib2<1dev,>=0.15.0
  Using cached httplib2-0.21.0-py3-none-any.whl (96 kB)
Collecting uritemplate<5,>=3.0.1
  Using cached uritemplate-4.1.1-py2.py3-none-any.whl (10 kB)
Collecting google-auth-httplib2>=0.1.0
  Using cached google_auth_httplib2-0.1.0-py2.py3-none-any.whl (9.3 kB)
Collecting google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0dev,>=1.31.5
  Using cached google_api_core-2.11.0-py3-none-any.whl (120 kB)
Collecting protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.19.5
  Using cached protobuf-4.21.12-cp37-abi3-macosx_10_9_universal2.whl (486 kB)
Collecting googleapis-common-protos<2.0dev,>=1.56.2
  Using cached googleapis_common_protos-1.58.0-py2.py3-none-any.whl (223 kB)
Collecting requests<3.0.0dev,>=2.18.0
  Using cached requests-2.28.2-py3-none-any.whl (62 kB)
Collecting cachetools<6.0,>=2.0.0
  Using cached cachetools-5.3.0-py3-none-any.whl (9.3 kB)
Collecting pyasn1-modules>=0.2.1
  Using cached pyasn1_modules-0.2.8-py2.py3-none-any.whl (155 kB)
Collecting six>=1.9.0
  Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting rsa<5,>=3.1.4
  Using cached rsa-4.9-py3-none-any.whl (34 kB)
Collecting pyparsing!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3,<4,>=2.4.2
  Using cached pyparsing-3.0.9-py3-none-any.whl (98 kB)
Collecting pyasn1<0.5.0,>=0.4.6
  Using cached pyasn1-0.4.8-py2.py3-none-any.whl (77 kB)
Collecting charset-normalizer<4,>=2
  Using cached charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl (122 kB)
Collecting urllib3<1.27,>=1.21.1
  Using cached urllib3-1.26.14-py2.py3-none-any.whl (140 kB)
Collecting certifi>=2017.4.17
  Using cached certifi-2022.12.7-py3-none-any.whl (155 kB)
Collecting idna<4,>=2.5
  Using cached idna-3.4-py3-none-any.whl (61 kB)
Installing collected packages: pyasn1, urllib3, six, rsa, pyparsing, pyasn1-modules, protobuf, idna, charset-normalizer, certifi, cachetools, requests, httplib2, googleapis-common-protos, google-auth, uritemplate, google-auth-httplib2, google-api-core, google-api-python-client
Successfully installed cachetools-5.3.0 certifi-2022.12.7 charset-normalizer-3.0.1 google-api-core-2.11.0 google-api-python-client-2.76.0 google-auth-2.16.0 google-auth-httplib2-0.1.0 googleapis-common-protos-1.58.0 httplib2-0.21.0 idna-3.4 protobuf-4.21.12 pyasn1-0.4.8 pyasn1-modules-0.2.8 pyparsing-3.0.9 requests-2.28.2 rsa-4.9 six-1.16.0 uritemplate-4.1.1 urllib3-1.26.14
(.venv) python % 
(.venv) python % pip install google_auth_oauthlib
Collecting google_auth_oauthlib
  Using cached google_auth_oauthlib-0.8.0-py2.py3-none-any.whl (19 kB)
Collecting requests-oauthlib>=0.7.0
  Using cached requests_oauthlib-1.3.1-py2.py3-none-any.whl (23 kB)
Requirement already satisfied: google-auth>=2.15.0 in ./.venv/lib/python3.9/site-packages (from google_auth_oauthlib) (2.16.0)
Requirement already satisfied: cachetools<6.0,>=2.0.0 in ./.venv/lib/python3.9/site-packages (from google-auth>=2.15.0->google_auth_oauthlib) (5.3.0)
Requirement already satisfied: six>=1.9.0 in ./.venv/lib/python3.9/site-packages (from google-auth>=2.15.0->google_auth_oauthlib) (1.16.0)
Requirement already satisfied: rsa<5,>=3.1.4 in ./.venv/lib/python3.9/site-packages (from google-auth>=2.15.0->google_auth_oauthlib) (4.9)
Requirement already satisfied: pyasn1-modules>=0.2.1 in ./.venv/lib/python3.9/site-packages (from google-auth>=2.15.0->google_auth_oauthlib) (0.2.8)
Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in ./.venv/lib/python3.9/site-packages (from pyasn1-modules>=0.2.1->google-auth>=2.15.0->google_auth_oauthlib) (0.4.8)
Requirement already satisfied: requests>=2.0.0 in ./.venv/lib/python3.9/site-packages (from requests-oauthlib>=0.7.0->google_auth_oauthlib) (2.28.2)
Collecting oauthlib>=3.0.0
  Using cached oauthlib-3.2.2-py3-none-any.whl (151 kB)
Requirement already satisfied: charset-normalizer<4,>=2 in ./.venv/lib/python3.9/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google_auth_oauthlib) (3.0.1)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./.venv/lib/python3.9/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google_auth_oauthlib) (1.26.14)
Requirement already satisfied: idna<4,>=2.5 in ./.venv/lib/python3.9/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google_auth_oauthlib) (3.4)
Requirement already satisfied: certifi>=2017.4.17 in ./.venv/lib/python3.9/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google_auth_oauthlib) (2022.12.7)
Installing collected packages: oauthlib, requests-oauthlib, google-auth-oauthlib
Successfully installed google-auth-oauthlib-0.8.0 oauthlib-3.2.2 requests-oauthlib-1.3.1
```

### 承認済みのリダイレクトURIの追加
試しにここで、「generate_report.py」を実行してみます。
```text
(.venv) python % python generate_report.py
```
`redirect_uri_mismatch`のエラーが発生します。
ここで、「エラーの詳細」をクリックします。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/dff0ef81-8787-2ba4-b697-c8c5ca1f6820.png">

リダイレクトURIに`http://localhost:8080/`を入れてくれと丁寧に書いてあるので、「OAuthクライアントID」に、このURIを追記します。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/ef946a7a-2a4b-e2a3-a6e0-f4db6302c103.png">

先ほど作ったOAuthクライアントIDの「承認済みのリダイレクトURI」に`http://localhost:8080/`を追加します。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/992ead90-4707-383b-d4f7-a27360b79fd2.png">

## レポート生成
もう一度、`generate_report.py`を実行してみます。
今度は「アカウントの選択」画面が表示されました。
使用するアカウントを選択します。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/c2555deb-3f9e-d2bf-5d5d-d143ebad9d03.png">

「続行」をクリックします。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/131037ab-434e-49c1-4924-eaaedb65da7e.png">

「認証が完了しました。ウィンドウを閉じてもよい」という旨のメッセージが表示されるので、ブラウザのウィンドウを閉じます。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/90e9ea3e-2b64-dd14-f817-21ad2bbff9b7.png">

もう一度`generate_report.py`を実行します。
今回はレポート結果が表示されました。
```text
(.venv) python % python generate_report.py
{'totalMatchedRows': '4', 'headers': [{'name': 'MONTH', 'type': 'DIMENSION'}, {'name': 'PLATFORM_TYPE_NAME', 'type': 'DIMENSION'}, {'name': 'PAGE_VIEWS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS_COVERAGE', 'type': 'METRIC_RATIO'}, {'name': 'CLICKS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS_CTR', 'type': 'METRIC_RATIO'}, {'name': 'COST_PER_CLICK', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}, {'name': 'AD_REQUESTS_RPM', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}, {'name': 'ESTIMATED_EARNINGS', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}], 'rows': [{'cells': [{'value': '2021-03'}, {'value': 'Other devices'}, {'value': '1'}, {'value': '2'}, {'value': '1'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '0'}]}, {'cells': [{'value': '2021-03'}, {'value': 'Tablets'}, {'value': '142'}, {'value': '428'}, {'value': '0.9533'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '6'}, {'value': '3'}]}, {'cells': [{'value': '2021-03'}, {'value': 'High-end mobile devices'}, {'value': '4028'}, {'value': '16179'}, {'value': '0.9906'}, {'value': '35'}, {'value': '0.0022'}, {'value': '18'}, {'value': '39'}, {'value': '633'}]}, {'cells': [{'value': '2021-03'}, {'value': 'Desktop'}, {'value': '7288'}, {'value': '27379'}, {'value': '0.9938'}, {'value': '17'}, {'value': '0.0006'}, {'value': '59'}, {'value': '37'}, {'value': '1011'}]}], 'totals': {'cells': [{}, {}, {'value': '11459'}, {'value': '43988'}, {'value': '0.9922'}, {'value': '52'}, {'value': '0.0012'}, {'value': '32'}, {'value': '37'}, {'value': '1647'}]}, 'averages': {'cells': [{}, {}, {'value': '2864'}, {'value': '10997'}, {'value': '0'}, {'value': '13'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '412'}]}, 'startDate': {'year': 2021, 'month': 3, 'day': 1}, 'endDate': {'year': 2021, 'month': 3, 'day': 31}}
                    MONTH       PLATFORM_TYPE_NAME               PAGE_VIEWS              AD_REQUESTS     AD_REQUESTS_COVERAGE                   CLICKS          AD_REQUESTS_CTR           COST_PER_CLICK          AD_REQUESTS_RPM       ESTIMATED_EARNINGS
                  2021-03            Other devices                        1                        2                        1                        0                        0                        0                        0                        0                  2021-03                  Tablets                      142                      428                   0.9533                        0                        0                        0                        6                        3                  2021-03  High-end mobile devices                     4028                    16179                   0.9906                       35                   0.0022                       18                       39                      633                  2021-03                  Desktop                     7288                    27379                   0.9938                       17                   0.0006                       59                       37                     1011
Report from {'year': 2021, 'month': 3, 'day': 1} to {'year': 2021, 'month': 3, 'day': 31}.
```

## 補足
### adsense_util.py
pythonディレクトリの中の、`adsense_util.py`を実行すると、次の実行からログインを求められずにレポートを生成できます。
`adsense_util.py`を実行すると、実行ディレクトリに`adsense.dat`ファイルが生成されます。
```text
(.venv) python % python adsense_util.py 
(.venv) python % ll -a                 
total 152
drwxrwxr-x@ 22 atsushi  staff   704  2  7 11:54 .
drwxrwxr-x@  8 atsushi  staff   256  2  7 11:15 ..
-rw-r--r--@  1 atsushi  staff  6148  2  7 11:43 .DS_Store
drwxr-xr-x   6 atsushi  staff   192  2  7 11:30 .venv
-rw-rw-r--@  1 atsushi  staff  1775  5 12  2022 README.md
drwxr-xr-x   3 atsushi  staff    96  2  7 11:42 __pycache__
-rw-r--r--   1 atsushi  staff   649  2  7 11:54 adsense.dat
-rw-rw-r--@  1 atsushi  staff  3378  5 12  2022 adsense_util.py
-rw-r--r--@  1 atsushi  staff   366  2  7 11:43 client_secrets.json
-rw-rw-r--@  1 atsushi  staff   273  5 12  2022 client_secrets.json.bk
-rw-rw-r--@  1 atsushi  staff  2890  5 12  2022 generate_report.py
-rw-rw-r--@  1 atsushi  staff  2065  5 12  2022 get_account_tree.py
-rw-rw-r--@  1 atsushi  staff  1811  5 12  2022 get_all_accounts.py
-rw-rw-r--@  1 atsushi  staff  2182  5 12  2022 get_all_ad_clients.py
-rw-rw-r--@  1 atsushi  staff  2551  5 12  2022 get_all_ad_units.py
-rw-rw-r--@  1 atsushi  staff  2811  5 12  2022 get_all_ad_units_for_custom_channel.py
-rw-rw-r--@  1 atsushi  staff  1944  5 12  2022 get_all_alerts.py
-rw-rw-r--@  1 atsushi  staff  2617  5 12  2022 get_all_custom_channels.py
-rw-rw-r--@  1 atsushi  staff  2703  5 12  2022 get_all_custom_channels_for_ad_unit.py
-rw-rw-r--@  1 atsushi  staff  2169  5 12  2022 get_all_payments.py
-rw-rw-r--@  1 atsushi  staff  2121  5 12  2022 get_all_saved_reports.py
-rw-rw-r--@  1 atsushi  staff  2573  5 12  2022 get_all_url_channels.py
```

### デフォルトでは2021年3月のレポート
デフォルトのプログラムでは2021年3月のレポート(2021年3月1日〜2021年3月31日)を取得するものとなっています。
`startDate_year`、`startDate_month`、`startDate_day`、`endDate_year`、`endDate_month`、`endDate_day`に代入する数値を適宜修正してください。
また、`metrics`や`dimensions`も適宜修正して、好みのレポートを生成してください。

### 昨日の収益のレポートを生成する
自分が修正したコードを共有させていただきます。
昨日の収益を取得するように、`generate_report.py`を少し修正しました。オリジナルのものはgitの公式のものを見てください。
* `datetime`から`datetime`と`timedelta`をインポート。
* 昨日の年月日を取得する`get_yesterday()`関数を作成。
* `main()`関数の中で`get_yesterday()`を呼び出す。
* 取得した昨日の年月日を、`startDate_year`、`startDate_month`、`startDate_day`、`endDate_year`、`endDate_month`、`endDate_day`に代入するように修正。
* `dimensions`を`DATE`に修正。
* `orderBy`を`+DATE`に修正。

```python:generate_report.py
#!/usr/bin/python
#
# Copyright 2021 Google LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Retrieves a saved report or generates a new one.

To get saved reports, run get_all_saved_reports.py.

Tags: accounts.reports.generate
"""

import adsense_util
import argparse
import sys
import google.auth.exceptions
from googleapiclient import discovery
from datetime import datetime, timedelta # 追記


# Declare command-line flags.
argparser = argparse.ArgumentParser(add_help=True)
argparser.add_argument(
    '--report_id',
    help='The ID of the saved report to generate.')

args = argparser.parse_args()
saved_report_id = args.report_id

### 追記(ここから) ###
def get_yesterday():
    yesterday = datetime.now() - timedelta(1)
    year = yesterday.year
    month = yesterday.month
    day = yesterday.day

    return year, month, day
### 追記(ここまで) ###

def main(argv):
  # Authenticate and construct service.
  credentials = adsense_util.get_adsense_credentials()
  with discovery.build('adsense', 'v2', credentials = credentials) as service:
    try:
      # Let the user pick account if more than one.
      account_id = adsense_util.get_account_id(service)

      # 昨日の年月日を取得する
      year, month, day = get_yesterday() # 追記

      # Retrieve report.
      if saved_report_id:
        result = service.accounts().reports().saved().generate(
            name=saved_report_id, dateRange='LAST_7_DAYS').execute()
      else:
        result = service.accounts().reports().generate(
            account=account_id, dateRange='CUSTOM',
            startDate_year=year, startDate_month=month, startDate_day=day, # year, month, dayに修正
            endDate_year=year, endDate_month=month, endDate_day=day, # year, month, dayに修正
            metrics=['PAGE_VIEWS', 'AD_REQUESTS', 'AD_REQUESTS_COVERAGE',
                    'CLICKS', 'AD_REQUESTS_CTR', 'COST_PER_CLICK',
                    'AD_REQUESTS_RPM', 'ESTIMATED_EARNINGS'],
            dimensions=['DATE'], # DATEに修正
            orderBy=['+DATE']).execute() # DATEに修正

      print(result)

      # Display headers.
      for header in result['headers']:
        print('%25s' % header['name'], end=''),
      print()

      # Display results.
      if 'rows' in result:
        for row in result['rows']:
          for cell in row['cells']:
            print('%25s' % cell['value'], end='')
      print()

      # Display date range.
      print('Report from %s to %s.' % (result['startDate'], result['endDate']))
      print()

    except google.auth.exceptions.RefreshError:
      print('The credentials have been revoked or expired, please delete the '
            '"%s" file and re-run the application to re-authorize.' %
            adsense_util.CREDENTIALS_FILE)


if __name__ == '__main__':
  main(sys.argv)
```
実行します。
```text
(.venv) python % python generate_report.py
{'totalMatchedRows': '1', 'headers': [{'name': 'DATE', 'type': 'DIMENSION'}, {'name': 'PAGE_VIEWS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS_COVERAGE', 'type': 'METRIC_RATIO'}, {'name': 'CLICKS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS_CTR', 'type': 'METRIC_RATIO'}, {'name': 'COST_PER_CLICK', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}, {'name': 'AD_REQUESTS_RPM', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}, {'name': 'ESTIMATED_EARNINGS', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}], 'rows': [{'cells': [{'value': '2023-02-06'}, {'value': '594'}, {'value': '2182'}, {'value': '0.9973'}, {'value': '2'}, {'value': '0.0009'}, {'value': '6'}, {'value': '5'}, {'value': '12'}]}], 'totals': {'cells': [{}, {'value': '594'}, {'value': '2182'}, {'value': '0.9973'}, {'value': '2'}, {'value': '0.0009'}, {'value': '6'}, {'value': '5'}, {'value': '12'}]}, 'averages': {'cells': [{}, {'value': '594'}, {'value': '2182'}, {'value': '0'}, {'value': '2'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '12'}]}, 'startDate': {'year': 2023, 'month': 2, 'day': 6}, 'endDate': {'year': 2023, 'month': 2, 'day': 6}}
                     DATE               PAGE_VIEWS              AD_REQUESTS     AD_REQUESTS_COVERAGE                   CLICKS          AD_REQUESTS_CTR           COST_PER_CLICK          AD_REQUESTS_RPM       ESTIMATED_EARNINGS
               2023-02-06                      594                     2182                   0.9973                        2                   0.0009                        6                        5                       12
Report from {'year': 2023, 'month': 2, 'day': 6} to {'year': 2023, 'month': 2, 'day': 6}.
```
WEB上で確認しましたが、数値は合っていました。
<img width="900" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/49d7bed8-ec37-55fc-d551-9f2167f40768.png">

# 参考サイト
https://pzgleaner.com/archives/adsense-request-via-api

https://www.lancork.net/2019/04/adsense-management-api-php-02-get-earnings-report#toc_title_2

https://www.lancork.net/2019/04/adsense-management-api-php-01-prepare-credentials/