#GAS #スクレイピング を便利にする「cheeriogs」を使ってスプレッドシートに登録する
JQueryを使っていると、スクレイピングでcheerioにはすごくお世話になりますが、GASでも使えるとは思わなかったです。
スクリプトIDは
1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0
なので、これを使っていきましょう。
# 実践
ソースコードで語ります。
## Before
var yearsname2ad = {
"元年": 2019,
};
const URL = PropertiesService.getScriptProperties().getProperties().url;
function __scraping ()
{
var html = UrlFetchApp.fetch( URL ).getContentText( 'UTF-8' ).replace( /\r?\n/g, "" ).replace( /[0-9]/g, function ( word )
{
return String.fromCharCode( word.charCodeAt( 0 ) - 0xFEE0 )
} );
var start = "<tbody>";
var end = "</tbody>";
return __cut( html, start, end );
}
var __match = {
tr: /\<tr \w(.*?)\<\/tr\>/g,
td: /\<td \w(.*?)\<\/td\>/g,
year: /[\d元](.*)年/g,
month: /年\d(.*)月/g,
day: /月\d(.*)日/g,
run: function ( str, pattern ) { return str.match( __match[ pattern ] ) },
}
function __cut ( str, sep )
{
return str.substring( str.indexOf( sep ) + sep.length, str.length );
}
function __rsubstring ( str, sep )
{
return str.substring( 0, str.indexOf( sep ) );
}
function __getYMD ( str, pattern )
{
var tmp = __match.run( str, pattern )[ 0 ]
switch ( pattern )
{
case "year":
tmp = yearsname2ad[ tmp ];
break;
case "month":
case "day":
tmp = tmp.substring( 1, tmp.length - 1 );
if ( tmp.length == 1 ) tmp = "0" + tmp;
break;
}
return tmp;
}
function __getDate ( str )
{
var year = __getYMD( str, "year" );
var month = __getYMD( str, "month" );
var day = __getYMD( str, "day" );
return year + "-" + month + "-" + day;
}
var table = __scraping()
var tr_items = __match.run( table, "tr" );
var td_items = tr_items.map( function ( tr )
{
var tds = __match.run( tr, "td" );
return tds.map( function ( td )
{
var clean_td = __rsubstring( __cut( td, ">" ), "<" )
.trim()
.replace( / /g, "" )
.replace( / /g, "" )
.replace( /\(/g, "" )
.replace( /\)/g, "" )
;
if ( clean_td.indexOf( "年" ) > -1 ) clean_td = __getDate( clean_td );
return clean_td;
} );
} );
td_items.shift();
## After
const years = [
{
name: "令和",
start: 2019,
},
];
function replaces ( str )
{
return getDate( str ).trim()
.replace( / /g, "" )
.replace( / /g, "" )
.replace( /\)/g, "" )
.replace( /\(/g, "" )
.replace( /[0-9]/g, function ( word )
{
return String.fromCharCode( word.charCodeAt( 0 ) - 0xFEE0 )
} );
}
function getDate ( str )
{
if ( str.indexOf( "年" ) == -1 ) return str;
var ad = -1; // 元年分を減らしておくため-1
years.forEach( function ( year )
{
if ( str.indexOf( year.name ) > -1 )
{
ad += year.start;
str = str.replace( year.name, "" );
}
} );
str = str.replace( "元", 1 )
var split = str.split( "年" ); // 2桁以上の検出に対応
return ( Number( split[ 0 ] ) + ad )
+ "-"
+ split[ 1 ].replace( "月", "-" ).replace( "日", "" );
}
const URL = PropertiesService.getScriptProperties().getProperties().url;
const content = UrlFetchApp.fetch( URL ).getContentText();
const $ = Cheerio.load( content );
var result = [];
var pointer = -1;
const EXCLUDE_COLUMN = 3; // 最初の行だけおかしなものがあるので除外
const COLUMNS = 4;
$( "td" ).each( function ( i, td )
{
if ( i < EXCLUDE_COLUMN ) return;
if ( i % COLUMNS == EXCLUDE_COLUMN )
{
result.push( [] );
pointer++;
}
result[ pointer ].push( replaces( $( td ).text() ) );
} );
行数はそんなに変わっていないのに、メンテナンス性が明らかに違いますね。
パターンマッチングを辞めたのは非常に大きいです。
※getDateとgetYMDは似たような事をやってるので統合しました。
# ヨタ話
Momentjsの出どころは私も気になっていました。
見た感じだとここが一番まともっぽい話をしていたのと、ソースが見れたので本スクリプトでも採用しています。
# 戻る
いいなと思ったら応援しよう!
のむらがあなたの役に立つ記事を書くためのコーヒーを一杯奢ってくれませんか?
サポートをすると、のむらの記事を使って、あなたの記事を盛り上げてみませんか?
また、有料記事などいただいた収益はすべて、あなたの代わりにアプリやツールを買って色々検証をして記事にするために使っています。