
副業情報を自動で集めて通知するツールを作ろう_1【GAS】【スクレイピング】
ランサーズ、クラウドワークスなどの副業サイトを見ていると数分で完了するアンケートが多数ありますね。報酬額は5~300円くらいで安いのですが、通勤時間や暇つぶし時間にちょこちょこやれば月5000円くらいは稼げそうです。5円で何百文字も書かせる案件があって泣きそうになることもあるけど、SNSを頑張ったりスマホゲームするよりは有意義です。
副業サイトは複数あるので、いちいち検索してまわるのは面倒です。そこで複数の副業サイトを定期的に検索して結果を一覧にまとめ、自動でメール通知する仕組みを作りたいと思います。通知された案件リンクリストから回答できそうなところをクリックしてどんどん回答して行くような運用をイメージしています。副業サイトにはメール通知設定がある場合もあるのですが自分は男性なのに女性限定案件が送られてきたりするので自作したいと思いました。
この記事の対象者
この記事ではこんな方のお悩みに答えます。
・できるだけコピペで簡単に何かを作ってみたい
・Google Apps Script(GAS)のサンプルが欲しい
・スクレイピングを試してみたい
・Google Apps Script(GAS)初心者の方もOK!
この記事で完成するもの
毎日定時に副業情報をメールで配信する仕組み
自動的にスプレッドシートに書き込まれて

下のようなメールが届く仕組みです。

プログラムをちょっと習った程度の人が、できるだけコピー&貼り付けで完成できるように説明して、細かい部分は今後の別の記事で解説します。3、4回くらいに記事を分けて改良も加えたいと思います。
(2021年3月時点ではこの方法で副業サイトの取り込みができますがサイト構成が変わるとできなくなるのでご注意ください)
使う技術
スクレイピング
GAS
・スクレイピングとは
WEBページの情報を抜き出して集める技術のことを言います。
・GASとは
GAS(Google Apps Script)はGmailやGoogleカレンダー、スプレッドシートなどのGoogleサービスを簡単に利用できるプログラミング言語。基本無料でGoogleアカウントとインターネットさえあればどこでも利用できます。今回はメール配信やスプレッドシート(エクセルみたいな表)、定時実行を利用したいのでGASを使います。事前にGoogleアカウントを取得してGMailとスプレッドシートが使えるようにしておいてください。
早速やってみよう
ランサーズの「アンケートを回答する」だけの案件を自動で検索してスプレッドシートに書き込むプログラムを作ってみます。ついでにメール送信も行います。
スプレッドシートを用意
GoogleにログインしてGoogleドライブから
「Googleスプレッドシート」-「空白のスプレッドシート」を選んで新規のスプレッドシートを作成します。名前は何でもよいです。

シートの中はB4からE4にかけて「No.、タイトル、詳細リンク、報酬額」と入力して下線を引いてください。

GASスクリプトファイル新規作成
スプレッドシートのメニューの「ツール」-「スクリプトエディタ」をクリックしてスクリプト画面を出します。

ライブラリを追加します
画面左側の「ライブラリ」の横の+ボタンを押します。


ライブラリの追加画面のスクリプトIDの部分に下の文字列を入力して
1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw
検索ボタンを押します。

「ライブラリParserを検索しました」と出たらバージョン番号を一番大きな数字に変えて追加ボタンを押します。このライブラリ(Parser)は文章から欲しい部分を切り抜くライブラリです。記事を書いている時点で最新バージョンは8でしたのでバージョンを8にします。
プログラムのコピー&ペースト

↑画面の赤枠あたりに元々入力されていた文字を全て消して、下のプログラムをコピー&ペーストしてください。
const SHEET = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
const PAGES = 3; //読み込むページ数
const main = () => {
//シートを初期化する
clearsheet();
let cnt_lancers = 0;
cnt_lancers = Scraping_Lancers();
let body = "ランサーズ" + cnt_lancers +"件";
SendMail(body);
}
const Scraping_Lancers = () => {
let cnt=0;
//ページ単位でスクレイピング
for(let page=1;page<=PAGES;page++){
const url = "https://www.lancers.jp/work/search?sort=started&type%5B0%5D=task&open=1&show_description=1&budget_from=&budget_to=&keyword=%E3%82%A2%E3%83%B3%E3%82%B1%E3%83%BC%E3%83%88¬=&work_rank%5B0%5D=2&work_rank%5B1%5D=3&work_rank%5B2%5D=0&page=${page}".replace("${page}", page);
const html = UrlFetchApp.fetch(url).getContentText('UTF-8');
Utilities.sleep(300);
const workArray = Parser
.data(html)
.from('<div class="c-media__content__right">')
.to('</div>')
.iterate();
for(let i =0;i<workArray.length;i++){
let content = workArray[i];
//案件タイトル
const p_title = Parser
.data(content)
.from('<span class="c-media__title-inner">')
.to('</span>')
.build();
let workTitle=deleteTag(p_title);
//詳細リンク
let workDetailurl='';
let workNumber='';
const p_detailurl_pos=content.indexOf('<a class="c-media__title" href="');
if(p_detailurl_pos != -1){
const p_detailurl_pos2=content.indexOf('">');
workDetailurl = "https://www.lancers.jp" + content.substr(p_detailurl_pos+32,p_detailurl_pos2-(p_detailurl_pos+32));
workNumber = content.substr(p_detailurl_pos+45,p_detailurl_pos2-(p_detailurl_pos+45));
}
//報酬額
let workPayment='';
const p_workPayment_pos=content.indexOf('<span class="c-media__job-price">');
if(p_workPayment_pos != -1){
workPayment = content.substr(p_workPayment_pos);
workPayment = deleteTag(workPayment);
}
//シートに書き込む
if(workNumber != '' ){
const lastrow = SHEET.getLastRow()+1;
SHEET.getRange(lastrow,2).setValue(workNumber);
SHEET.getRange(lastrow,3).setValue(workTitle);
SHEET.getRange(lastrow,4).setValue(workDetailurl);
SHEET.getRange(lastrow,5).setValue(workPayment);
Utilities.sleep(50);
cnt+=1;
}
}
Utilities.sleep(300);
//次へのリンクが無かったら中断する
if(html.indexOf('<span class="pager__item pager__item--next">')==-1){
break;
}
}
return cnt;
}
const clearsheet = () =>{
const lastrow = SHEET.getLastRow();
if(lastrow-4 > 0) {
SHEET.getRange(5,1,lastrow-4,10).setValue("");
}
}
const deleteTag = (str) =>{
let ret = str.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'')
ret = ret.replace(/[\s\t\n]/g,"");
return ret;
}
const SendMail = (body) => {
//案件検索結果
//〇月〇日の検索結果
//ランサーズ 〇件
// 送信時間
let today = Utilities.formatDate(new Date(), 'JST', 'yyyy年M月d日 H時m分s秒');
// メールタイトル
let subject = "案件検索結果" + today;
//送信先メールアドレス
let address = Session.getActiveUser().getEmail(); //あなたのメールアドレス
let link_sheet = SpreadsheetApp.getActiveSpreadsheet().getUrl();
//メール本文
let mailbody = "\nお疲れ様です。\n本日"+today+"時点での検索結果を送ります。\n"+ body + "\n" + link_sheet;
GmailApp.sendEmail(address,subject,mailbody);
}

変数addressが送信先メールアドレスになっています。自分のGmailアドレス以外に送りたいときは、上の青色の部分のように変更します。とりあえず試すだけなら変更しなくても結構です。
動作テスト

動作テストしてみます。テストするにはメニューの中の「デバック」ボタンを押します。デバックの右横はテストする関数名なので「main」にしておいてください。
デバッグボタンを押すと下のような警告がでるかもしれません。「権限を確認」を押してください。

「権限を確認」を押すと、下の画面に変わります。
自分のアカウントをクリック

「このアプリはGoogleで確認されていません」と表示されてビックリするかもしれません。左下側に小さく表示されている「承認」をクリック

「~(安全ではないページ)に移動」をクリック

「許可」をクリック

実行すると下のようになります

メールも届いたら、ひとまず完成です。

※※※注意※※※
Googleアカウントが「Gmailの無いアカウント」の場合だとメール送信のところでエラーが出てしまいます。そのときは改めてGmail付きのGoogleアカウントをご用意ください。
※※※※※※※※
プログラム2行目のPAGESの数値がランサーズの検索ページから読み込むページ数です。お試しなので検索結果3ページ分だけ取り込むように制限しました。2行目のconst PAGES = 3、ここのところを増やせば全ページも読み込みもできます。
予告
とりあえず動作するものは作れました。
次回は定期実行と別の副業サイトのスクレイピングを行いたいと思います。
#スクレイピング #プログラミング #GAS #副業 #自動化ツール #無料配布 #コピペで使えるGAS #クラウドワークス #ランサーズ
おススメの本
GASを勉強したい人におススメの本は「Google Apps Scriptのツボとコツがゼッタイにわかる本」がいいです。
「~のツボとコツがゼッタイにわかる本」シリーズは他の言語も読みやすくていいですよ。私は「PHPとMySQLのツボとコツがゼッタイにわかる本」も持ています。