こんにちは。投資エンジニアの三年坊主(@SannenBouzu)です。
今回は、ブログでアフィリエイトをはじめて数か月になる初心者の悩みに答えます。
アフィリエイトサイトの成果レポートを1クリックで集計したい。1サイトずつ確認しても収益が出ていない日も多いので、なるべく手間と時間をかけずに確認して、ブログ運営に注力したい。
このブログは2018年7月に運営をはじめて、現在は少しですが収益が発生する日が出てきました。
とは言え発生しない日の方が多く、複数のアフィリエイトサイト(ASP)にわざわざログインしたにも関わらず「収益0」の数字を見ると少し悲しくなってしまいます。
この記事では、私の経験も踏まえて、なるべく手間と時間をかけずにアフィリエイトサイトの成果レポートを確認・集計する方法を紹介します。
- アフィリエイトサイトの成果レポートを一つずつ確認・集計するのが面倒くさい方
- 収益が出た記事と金額の一覧を1クリックで確認したい方
アフィリエイトサイトの成果レポートと問題点
成果レポートはアフィリエイト収益を伸ばす大切な情報源
「成果レポート」は、アフィリエイトサイト(ASP)経由で発生・確定した収益などの成果をチェックできるレポートのことですね。
アフィリエイトを用いたブログ収益化を意識するなら、アフィリエイトサイト(ASP)の成果レポートで、収益が出た自分のブログ記事と金額をチェックすることが大切です。
収益が生まれた記事は毎日チェックしましょう。これは僕の日課でもあるのですが、全てのASPに毎日ログインします。
アフィリエイトサイトのアクセス解析方法【収益アップの必須タスク】
複数アフィリエイトサイトへのログイン・確認が大変
ささいなことではありますが、複数のアフィリエイトサイトに登録していると、一つずつログインしてレポートを確認・集計するのに時間がかかるという問題があります。
私が登録しているアフィリエイトサイトの一例
さらに言えば、冒頭で触れた私のように、アフィリエイトサイトにログインしたのに収益が全く発生していない日が多いと、少し悲しいですよね。
実際に収益が出た自分のブログ記事を手軽に確認して、できることなら毎日収益が発生するように、ブログ運営のヒントを得たいものです。
次の見出しでは、なるべく手間と時間をかけずに、成果レポートを確認・集計する方法を紹介します。
アフィリエイトサイトの成果レポートを1クリックで確認【自動化で収益アップ?】
私自身、複数のアフィリエイトサイトにログインして、一つずつ成果レポートを確認するのが面倒くさいと感じることが多かったので、ブラウザ上で1クリックで確認できるプログラムを組みました。
リンク先のGoogle Colaboratoryを自分のGoogle Driveにコピーして、ASPごとの収益を1件ずつ確認することが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 | # A8 asp_name = 'A8' my_asp = asp_instance(asp_name, credentials[asp_name]['login_id'], credentials[asp_name]['password']) my_asp.login() my_asp.get_data() table_df_a8 = my_asp.prettify_data() # バリューコマース asp_name = 'バリューコマース' my_asp = asp_instance(asp_name, credentials[asp_name]['login_id'], credentials[asp_name]['password']) my_asp.login() my_asp.get_data() table_df_valuecommerce = my_asp.prettify_data() |
また、ASP・リファラーごとに集計した成果レポートを見ることができます。
1 2 3 4 5 | all_columns = ['ASP', '注文日', 'プログラム', '発生報酬(円)', 'リファラー'] table_df_a8.columns = all_columns table_df_valuecommerce.columns = all_columns table_df_all = pd.concat([table_df_a8, table_df_valuecommerce]) |
Google Colaboratoryは、Web上で一瞬でPythonの実行環境を用意できるツールです。
使い方や実際の使用例は、【Webブラウザで15分】見る人の心に残るワードクラウド作成手順を徹底解説【現役エンジニアのPythonチュートリアル】などを参照してください。
おおまかな実行手順は以下の通りです。
- アフィリエイトサイト(ASP)ごとのIDを入力
- 「ランタイム」→「すべてのセルを実行」をクリック
- アフィリエイトサイトごとのパスワードを入力
- ページ最下部の出力結果を確認
アフィリエイトサイトのIDとパスワードを安全に取り扱う
今回は、自分のアカウントで成果レポートを実際に検証できた、A8.net
Google Colaboratoryの「フォーム」という機能を使って、IDを動的に入力できます。
1 2 3 | #@title アフィリエイトサイト(ASP)ごとのID login_id_a8 = 'login_id' #@param {type:"string"} login_mail_valuecommerce = 'aaa@example.com' #@param {type:"string"} |
パスワードは、そのまま画面に出力されないように、Pythonの標準ライブラリgetpassを使いましょう。
1 2 3 | from getpass import getpass password_a8 = getpass('パスワードを入力 (A8)') password_valuecommerce = getpass('パスワードを入力 (バリューコマース)') |
アフィリエイトサイトのログイン情報をGoogle Colaboratoryで入力するのに抵抗がある方は、自分のパソコンでPython環境を作ってコードを実行することも可能です。
必要なライブラリをインポートします。
1 2 3 4 5 6 7 8 9 10 | # Selenium ライブラリをインポート from selenium import webdriver from selenium.webdriver.chrome.options import Options # 遷移したページの状態を確認 from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import pandas as pd |
アフィリエイトサイトをブラウザ操作して成果レポートを自動で取得する
「アフィリエイトサイトにログインして、自分の手で成果レポートを探す」操作を自動化するために、Pythonのクラスをいくつか定義します。
親クラス「ASP」
基本的には、どのアフィリエイトサイト(ASP)でも変わらない、共通の操作内容をこのクラスに定義します。
- IDとパスワードを入力してログイン
- レポートのページに遷移
- 日付を指定して検索
- 出力結果を取得・整形
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | from abc import ABCMeta, abstractmethod import time class ASP(metaclass=ABCMeta): """ ASPにログインし操作するための親クラス。 """ def __init__(self, asp_name, login_url, login_id, password, report_url, loginid_selector, password_selector, loginbutton_selector, startdate_selector, enddate_selector, searchbutton_selector, reporttable_selector, start_date, end_date, report_columns, report_columns_selected): print('in ASP init') self.asp_name = asp_name self.login_url = login_url self.login_id = login_id self.password = password self.report_url = report_url self.driver = self.prepare_driver() # ログインに関するDOMを指定 self.loginid_selector = loginid_selector self.password_selector = password_selector self.loginbutton_selector = loginbutton_selector # レポートに関するDOMを指定 self.startdate_selector = startdate_selector self.enddate_selector = enddate_selector self.searchbutton_selector = searchbutton_selector self.reporttable_selector = reporttable_selector # レポートの日付 self.start_date = start_date self.end_date = end_date # レポートの列 self.report_columns = report_columns self.report_columns_selected = report_columns_selected # DataFrame self.result_df = None def prepare_driver(self): # ブラウザをheadlessモード(バックグラウンドで動くモード)で立ち上げる options = webdriver.ChromeOptions() options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') driver = webdriver.Chrome('chromedriver',options=options) driver.implicitly_wait(10) return driver #@abstractmethod def login(self): print('in {} login'.format(self.asp_name)) # 1-1. ログインページに遷移 self.driver.get(self.login_url) if self.asp_name == 'バリューコマース': # (バリューコマース特有:iframeに切り替え) iframe = self.driver.find_element_by_xpath('//*[@id="frame1"]') self.driver.switch_to.frame(iframe) # 1-2. IDを入力(要素が出現するまで最大5秒待つ) id_elem = WebDriverWait(self.driver, 5).until( EC.presence_of_element_located((By.XPATH, self.loginid_selector)) ) id_elem.send_keys(self.login_id) # 1-3. パスワードを入力(要素が出現するまで最大5秒待つ) password_elem = WebDriverWait(self.driver, 5).until( EC.presence_of_element_located((By.XPATH, self.password_selector)) ) password_elem.send_keys(self.password) # 1-4. ログインボタンをクリック login_button = self.driver.find_element_by_xpath(self.loginbutton_selector) login_button.click() if self.asp_name == 'バリューコマース': # (バリューコマース特有:iframeから戻る) self.driver.switch_to.default_content() #@abstractmethod def get_data(self): print('in {} get_data'.format(self.asp_name)) # 2-1. ログイン状態でレポートページに遷移 self.driver.get(self.report_url) # 2-2. 開始日選択:データが存在する日付を指定(要素が出現するまで最大5秒待つ) datepicker_from_elem = WebDriverWait(self.driver, 5).until( EC.presence_of_element_located((By.ID, self.startdate_selector)) ) datepicker_from_elem.clear() datepicker_from_elem.send_keys(self.start_date) # 2-3. 終了日選択:データが存在する日付を指定(要素が出現するまで最大5秒待つ) datepicker_to_elem = WebDriverWait(self.driver, 5).until( EC.presence_of_element_located((By.ID, self.enddate_selector)) ) datepicker_to_elem.clear() datepicker_to_elem.send_keys(self.end_date) # 2-4. 検索ボタンをクリック search_button = self.driver.find_element_by_xpath(self.searchbutton_selector) search_button.click() # 2-5. 表を取得(要素が出現するまで最大5秒待つ) report_table = WebDriverWait(self.driver, 5).until( EC.presence_of_element_located((By.XPATH, self.reporttable_selector)) ) # 2-6. 表をpandasのDataFrameとして操作 report_table_html = report_table.get_attribute('outerHTML') table_df = pd.read_html(report_table_html)[0] self.result_df = table_df @abstractmethod def prettify_data(self): '''このメソッドを子クラスでオーバーライドする https://stackoverflow.com/questions/44576167/force-child-class-to-override-parents-methods ''' pass @abstractmethod def toYenInt(self, row): '''このメソッドを子クラスでオーバーライドする https://stackoverflow.com/questions/44576167/force-child-class-to-override-parents-methods ''' pass |
「共通の操作内容」と言いつつ、「バリューコマース特有」という文字が見えますね。
「IDとパスワードを入力してログインボタンを押す」というサイトログインの処理は、サイトに関わらず共通する部分がかなり多いので、この親クラスにまとめた方が見通しがいいかなと判断しています。
XPATHは、HTMLから特定の部分を指定して抽出する方法です。
一見難しそうですが、Chromeのinspectorを使って確認できるのでそこまで厳密に理解しなくても使えます。
子クラス「A8」
親クラス「ASP」のクラス変数と機能を引き継ぎながら(継承)、A8.netに特有の処理を定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | class A8(ASP): """ A8にログインし操作するためのクラス。 ID/パスワードに関係するHTMLの抜粋は以下 A8: <li class="idInput"><input type="text" name="login" autocomplete="on" value="" tabindex="1" id="asLoginId"></li> A8: <li class="passInput"><input type="password" autocomplete="on" name="passwd" value="" tabindex="2"></li> ログインボタンに関係するHTMLの抜粋は以下 A8: <li class="lgnBtn"><input type="image" name="lgin_as_btn" src="/wp/wp-content/themes/a8theme/images/lgin_as_btn.gif" alt="ログイン" tabindex="3"></li> """ def __init__(self, login_id, password): asp_name = 'A8' print('in {} init'.format(asp_name)) login_url = 'https://www.a8.net/' report_url = 'https://pub.a8.net/a8v2/asCvrRefferReportAction.do' # ログインに関するDOMを指定 loginid_selector = '//*[@id="asLoginId"]' password_selector = '//*[@id="headerLeft"]/form/ul/li[2]/input' loginbutton_selector = '//*[@id="headerLeft"]/form/ul/li[3]/input' # レポートに関するDOMを指定 startdate_selector = 'jquery-ui-datepicker-from' enddate_selector = 'jquery-ui-datepicker-to' searchbutton_selector = '//*[@id="sitereport"]/form/ul/li[2]/input' reporttable_selector = '//*[@id="reportSortTable"]' # レポートの日付 start_date = '2018/10/01' end_date = '2018/10/31' # レポートの列 report_columns = ['クリック日', '注文日', '確定日', 'オーダーID', 'プログラムID', '広告主名・プログラム名', '注文金額', '発生報酬額', '確定報酬額', 'ステータス', 'デバイス', 'リファラ'] report_columns_selected = ['ASP', '注文日', '広告主名・プログラム名', '発生報酬額', 'リファラ'] super().__init__(asp_name, login_url, login_id, password, report_url, loginid_selector, password_selector, loginbutton_selector, startdate_selector, enddate_selector, searchbutton_selector, reporttable_selector, start_date, end_date, report_columns, report_columns_selected) def prettify_data(self): print('in {} prettify_data'.format(self.asp_name)) # (A8特有:列名を指定、ASP名追加、金額を数字に変換) self.result_df.columns = self.report_columns self.result_df['ASP'] = self.asp_name self.result_df = self.result_df.apply(self.toYenInt, axis=1) return self.result_df[self.report_columns_selected] def toYenInt(self, row): rewards = row['発生報酬額'].replace(',', '') pos = rewards.find(' 円') if pos < 0: rewards = int(float(rewards)) else: rewards = int(float(rewards[:pos])) row['発生報酬額'] = rewards return row |
子クラス「ValueCommerce」
バリューコマースについても同様に、特有の処理を定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | class ValueCommerce(ASP): """ バリューコマースにログインし操作するためのクラス。 ID/パスワードに関係するHTMLの抜粋は以下 <input type="email" id="login_form_emailAddress" name="login_form[emailAddress]" required="required"> <input type="password" id="login_form_encryptedPasswd" name="login_form[encryptedPasswd]" required="required"> ログインボタンに関係するHTMLの抜粋は以下 <input type="submit" value="ログイン" class="btn_green"> """ def __init__(self, login_id, password): asp_name = 'バリューコマース' print('in {} init'.format(asp_name)) login_url = 'https://www.valuecommerce.ne.jp/' report_url = 'https://aff.valuecommerce.ne.jp/report/transactions' # ログインに関するDOMを指定 loginid_selector = '//*[@id="login_form_emailAddress"]' password_selector = '//*[@id="login_form_encryptedPasswd"]' loginbutton_selector = '//*[@id="login_aff"]/input[1]' # レポートに関するDOMを指定 startdate_selector = 'from_date' enddate_selector = 'to_date' searchbutton_selector = '//*[@id="search"]' reporttable_selector = '//*[@id="report_area"]/table' # レポートの日付 start_date = '2018/12/01' end_date = '2018/12/31' # レポートの列 report_columns = ['No', 'クリック日', '注文日', '処理日', '注文ID', '広告主', 'プログラム', '注文個数', '注文金額', '報酬金額(税抜)', '消費税', '報酬金額(税込)', 'ステータス', '承認期限', 'リファラー', 'デバイス'] report_columns_selected = ['ASP', '注文日', 'プログラム', '報酬金額(税込)', 'リファラー'] super().__init__(asp_name, login_url, login_id, password, report_url, loginid_selector, password_selector, loginbutton_selector, startdate_selector, enddate_selector, searchbutton_selector, reporttable_selector, start_date, end_date, report_columns, report_columns_selected) def prettify_data(self): print('in {} prettify_data'.format(self.asp_name)) # (バリューコマース特有:列名を指定、ASP名追加、1行目と最終行をレコードから取り除く、金額を数字に変換) self.result_df.columns = self.report_columns self.result_df['ASP'] = self.asp_name self.result_df.drop(self.result_df.head(1).index,inplace=True) # drop first 1 rows self.result_df.drop(self.result_df.tail(1).index,inplace=True) # drop last 1 rows self.result_df = self.result_df.apply(self.toYenInt, axis=1) return self.result_df[self.report_columns_selected] def toYenInt(self, row): rewards = int(float(row['報酬金額(税込)'].replace(',', '').replace('¥', ''))) row['報酬金額(税込)'] = rewards return row |
成果レポートを確認・集計して収益アップ?
このようにクラスを定義してしまえば、後はそれを使うだけなので簡単です。
自分でアフィリエイトサイトを追加したくなっても、結構簡単に追加できるようになっています。
1 2 3 4 5 6 7 | def asp_instance(asp_name, login_id, password): if asp_name == 'A8': return A8(login_id, password) elif asp_name == 'バリューコマース': return ValueCommerce(login_id, password) else: raise ValueError('Invalid ASP name: {}'.format(asp_name)) |
発生した収益を1件1件確認したり、
1 2 3 4 5 6 | # バリューコマース asp_name = 'バリューコマース' my_asp = asp_instance(asp_name, credentials[asp_name]['login_id'], credentials[asp_name]['password']) my_asp.login() my_asp.get_data() table_df_valuecommerce = my_asp.prettify_data() |
ASP・リファラーごとに集計した成果レポートを見ることができます。
1 2 3 4 5 | all_columns = ['ASP', '注文日', 'プログラム', '発生報酬(円)', 'リファラー'] table_df_a8.columns = all_columns table_df_valuecommerce.columns = all_columns table_df_all = pd.concat([table_df_a8, table_df_valuecommerce]) |
まだ考慮できていないケースもいくつかあって、以下はその一例です。
- 成果データが存在するようなレポートの日付を選べない
- 成果データが多すぎて1ページにおさまらない
成果レポートの確認・集計を自動化して、収益アップにつながるブログ運営を目指してみませんか?