はじめに
QiitaでKonaさんの記事を読んでいてGASを使ってドライブに自動保存できないかと思ったので作成。
前の月のブログの画像を毎日午前と午後に2人分、最大2*28(2月が28日間しかないので)=56人分保存できる。
とりあえずコード全体
blog.js
const memberList = [48006];
function getEntrysFromMember(memberId, startMask, endMask) {
const entrysList = new Array();
for (let page = 0; true; page++) {
const startLength = entrysList.length;
const html = UrlFetchApp.fetch(`https://www.nogizaka46.com/s/n46/diary/MEMBER/list?page=${page}&ct=${memberId}`).getContentText("UTF-8");
const entrys = Parser.data(html).from("<a class=\"bl--card js-pos a--op hv--thumb\"").to("</a>").iterate();
const memberName = Parser.data(html).from("<p class=\"bd--prof__name f--head\">").to("</p>").build().replace(/\s+/g, "") ?? memberName;
for (const entry of entrys) {
const entryDate = new Date(Parser.data(entry).from("<p class=\"bl--card__date\">").to("</p>").build());
if (startMask <= entryDate) {
if (entryDate < endMask) {
const entryUrl = Parser.data(entry).from("href=\"").to("\">").build();
entrysList.push([entryUrl, entryDate]);
}
} else {
return [memberName, entrysList];
}
}
if (entrysList.length != 0 && entrysList.length == startLength) {
return [memberName, entrysList];
}
}
}
function downloadImages(memberName, entrys) {
let imgInfoMap = new Map();
for (const entry of entrys) {
const html = UrlFetchApp.fetch(`https://www.nogizaka46.com${entry[0]}`).getContentText("UTF-8");
const bodys = Parser.data(html).from("<div class=\"bd--edit\">").to("<div class=\"bd--pnv js-pos a--op\">").build().match(/(src=)["|'](.*?)\.(jpg|png|jpeg)["|']+/g);
if (bodys == null) {
continue;
}
const imgUrls = new Array();
const dateStr = Utilities.formatDate(entry[1], "Asia/Tokyo", "yyyyMMdd");
for (const body of bodys) {
for (const url of body.match(/(images|files)(\/.*?)\.(jpg|png|jpeg)+/g)) {
if (url.match(/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+/g)) {
imgUrls.push(url);
}
}
}
if (typeof imgInfoMap.get(dateStr) === "undefined") {
imgInfoMap.set(dateStr, imgUrls);
} else {
imgInfoMap.set(dateStr, imgUrls.concat(imgInfoMap.get(dateStr)));
}
}
let folder = DriveApp.getRootFolder().getFoldersByName("乃木坂46").next();
try {
folder = folder.getFoldersByName(memberName).next();
} catch (e) {
folder.createFolder(memberName);
folder = folder.getFoldersByName(memberName).next();
}
folder = folder.getFoldersByName("blog").next();
const files = folder.getFiles();
const filesList = new Array();
while (files.hasNext()) {
filesList.push(files.next().getName());
}
for (const imgInfo of imgInfoMap) {
console.log(`Processing ${imgInfo[0]}`);
for (let i = 0; i < imgInfo[1].length; i++) {
const fileName = `${imgInfo[0]}_${i + 1}.jpeg`;
if (filesList.indexOf(fileName) < 0) {
const response = UrlFetchApp.fetch(`https://www.nogizaka46.com/${imgInfo[1][i]}`);
const fileBlob = response.getBlob().setName(fileName);
const file = DriveApp.createFile(fileBlob);
file.makeCopy(file.getName(), folder);
file.setTrashed(true);
}
}
}
}
function pictureGetterEveryMonth() {
const startDay = new Date();
const endDay = new Date();
const index = startDay.getHours() / 12 | 0 ? (startDay.getDate() - 1) * 2 + 1 : (startDay.getDate() - 1) * 2;
if (index < memberList.length) {
startDay.setMonth(startDay.getMonth() - 1);
startDay.setDate(1);
endDay.setDate(31);
const retVal = getEntrysFromMember(memberList[index], startDay, endDay);
if (retVal[0] != undefined) {
downloadImages(retVal[0], retVal[1]);
}
}
}
使用方法
1.Google Drive上に画像を保存するためのフォルダを作る
- 今回はルート直下に以下のような構成で作成
乃木坂46
└── 遠藤さくら
└── blog ←ここに保存する
2.プロジェクトの作成
Google Apps Scriptでプロジェクトを作成してコードを貼り付ける。
3.ライブラリ追加
ライブラリの横の+マークを押し、スクリプトIDに
1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw
を入力してParserライブラリを追加する
4.トリガーを設定する
pictureGetterEveryMonthを午前と午後に毎日実行するために以下のような2つのトリガーを作成する。
(実行する時刻は午前と午後に分かれていればいつでも良い)
保存したいメンバーの追加
公式サイトのBLOG→メンバーを選択からメンバーを選択する。
その後表示されるページのURLのct=
のあとの数字をソースコードの最初にあるmemberList
内に記載する。
例えば、遠藤さくらちゃんの場合はURLがhttps://www.nogizaka46.com/s/n46/diary/MEMBER/list?ima=0115&ct=48006
なので48006
を記載する
各関数のざっくりとした解説
今後追記予定