Skip to content

Instantly share code, notes, and snippets.

@59t9
Last active March 7, 2024 10:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 59t9/666901916c2d06332f7f3a659da5e255 to your computer and use it in GitHub Desktop.
Save 59t9/666901916c2d06332f7f3a659da5e255 to your computer and use it in GitHub Desktop.
ナウキャストの画像取得(20240307版) by puppeteer/node.js
const puppeteer = require('puppeteer');
const fs = require('fs');
require('date-utils');
const { WebClient } = require('@slack/web-api');
const setTimeout = require("node:timers/promises").setTimeout;
async function selectorClicker(page, selector) {
await page.waitForSelector(selector);
const elementHandleList = await page.$$(selector);
await elementHandleList[0].click();
await setTimeout(1000);
}
const isExists = filePath =>{
try{
const data = fs.statSync(filePath);
return data;
}catch(e){
return false;
}
}
async function slack_notify(msg) {
const token = 'your token';
// #チャンネル名 of @ユーザー名
const channel = '#somewhere';
const username = 'username';
// メッセージ
const client = new WebClient(token);
const params = {
channel: channel,
text: msg,
username: username
};
const response = await client.chat.postMessage(params);
console.log(response);
}
(async () => {
const now = new Date();
let dateTemp = new Date();
dateTemp.setHours(now.getHours()-1);
const saveTimeOntheClock = new Date(dateTemp.getFullYear(), dateTemp.getMonth(), dateTemp.getDate(), dateTemp.getHours());
// ブラウザ表示域のサイズで画像サイズが決まる
const browser = await puppeteer.launch({headless: true, 'defaultViewport' : { 'width' : 1048, 'height' : 1000 }});
console.log(saveTimeOntheClock.toFormat('YYYY/MM/DD HH24:MI:SS'));
try{
let loop_count = 0
const page = await browser.newPage();
const cdpSession = await page.target().createCDPSession();
await cdpSession.send("Browser.setDownloadBehavior", {
behavior : 'allow',
downloadPath: fs.realpathSync('./')
});
await page.goto('https://www.jma.go.jp/bosai/nowc/#zoom:N/lat:AAA.AAAAAA/lon:OOO.OOOOOO/colordepth:normal/elements:hrpns', {waitUntil: "domcontentloaded"});
//await page.screenshot({path: 'jma000.png'});
// 最新時刻への更新
{
const selector = 'button[id^="jmatile_refresh_"]';
await selectorClicker(page, selector);
}
//await page.screenshot({path: 'jma001.png'});
// セーブしたい時刻(X時55分)への移動
while (loop_count < 60) {
const selector = 'div[class="noUi-tooltip"]';
await page.waitForSelector(selector);
const elementHandleList = await page.$$(selector);
let value = await (await elementHandleList[0].getProperty('textContent')).jsonValue();
console.log(value);
let clock = value.split(':');
let hour = saveTimeOntheClock.getHours();
//await page.screenshot({path: 'jma002_' + clock[0] + clock[1] + '.png'});
if (clock[0] == hour && clock[1] == '55') {
loop_count = 0;
break;
}
// 5分過去へ
loop_count++;
{
const selector = 'button[id^="jmatile_time_prev_"]';
await selectorClicker(page, selector);
}
}
if (loop_count > 0) {
throw 'Give up!';
}
// X時(5*i)分の画像取得 リカバリ分を含めて120分
for(let i=0; i<120/5; i++){
let clock = [];
{
const selector = 'div[class="noUi-tooltip"]';
await page.waitForSelector(selector);
const elementHandleList = await page.$$(selector);
const value = await (await elementHandleList[0].getProperty('textContent')).jsonValue();
console.log(value);
clock = value.split(':');
}
// 保存先を決める
const srcDate = new Date(dateTemp.getFullYear(), dateTemp.getMonth(), dateTemp.getDate(), clock[0], clock[1]);
const srcDateUTC = srcDate.toUTCFormat('YYYYMMDDHH24MISS');
const srcfile = fs.realpathSync('./') + '/' + 'nowc_hrpns_' + srcDateUTC + '_' + srcDateUTC + '.png';
const dstdir = fs.realpathSync('./') + '/' + saveTimeOntheClock.toFormat('YYYY/MM/DD');
const dstfile = dstdir + '/' + saveTimeOntheClock.toFormat('YYYYMMDD') + '_' + clock[0] + clock[1] + '.png';
fs.mkdirSync(dstdir, { recursive: true });
if (isExists(dstfile) == false){
// メニュー出し
{
const selector = 'div[class="area-toggle"]';
await selectorClicker(page, selector);
}
// 画像保存
{
const selector = 'div[class="area-download"]';
await selectorClicker(page, selector);
}
let retry = 0;
while (isExists(srcfile) == false && retry < 10) {
await setTimeout(1000); // sure to be created
retry++;
}
if (isExists(srcfile) == false){
console.log(srcfile + ' not found.');
}
else{
console.log(srcfile);
fs.renameSync(srcfile, dstfile);
}
}
// 5分過去へ
{
const selector = 'button[id^="jmatile_time_prev_"]';
await selectorClicker(page, selector);
}
//await page.screenshot({path: 'jma003_' + clock[0] + clock[1] + '.png'});
}
} catch(e) {
console.log(e.message);
slack_notify('jmacapt.js: Error. check log.')
} finally {
await browser.close();
}
})();
@59t9
Copy link
Author

59t9 commented Aug 13, 2022

久しぶりにOSを更新したついでに
Chrome DevTools Protocol
というものでダウンロード先を指定するようにした。

@59t9
Copy link
Author

59t9 commented Mar 7, 2024

waitForXPathやwaitForTimeoutが使えなくなるため、代替手段に切替え。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment