姉妹記事
✅技術要素
- JavaScript for Automation (JXA)を使って、Safariを操作します
- PDF出力するサイトのURLは、あらかじめテキストファイルに記述しておきます
- ファイルオープンダイアログを表示して、指定されたURLリストを読み込み処理します
macOS 26.1 (25B78)
Safari 26.1 (21622.2.11.11.9)
AppleScript 2.8
✅URLリスト(テキストファイル)
-
単純に、1行:1URLで記述します
URL_list.txthttps://qiita.com/nak435/items/800dbda782f4fe9c7df1 https://qiita.com/nak435/items/67aca33ca49b6f328faa https://qiita.com/nak435/items/d6d9782d43c5e948447b https://qiita.com/nak435/items/02fb97a666f0596c0316
✅AppleScrip(JXA)スクリプト
・ Safariの開発タブ
「Apple Event からの JavaScript を許可」にチェック✅
これを忘れると、次のエラーとなります。
You must enable 'Allow JavaScript from Apple Events' in the Developer section of Safari Settings to use 'do JavaScript'.
・ スクリプトエディタで JavaScript を選択
・ コード
// JavaScript for Automation (JXA)
(function() {
const app = Application.currentApplication();
app.includeStandardAdditions = true;
const safari = Application("Safari");
const systemEvents = Application("System Events");
const safariProcess = systemEvents.processes.byName("Safari");
// URLリストのファイル選択
const filePath = app.chooseFile({ withPrompt: "URLリストのテキストファイルを選択してください。" });
const content = app.read(filePath);
const urlList = content.split(/[\r\n]+/);
// Safariの準備
if (safari.windows.length === 0) {
safari.documents.push(safari.Document());
delay(1);
}
let urlCount = 1;
for (let aUrl of urlList) {
if (aUrl.trim() === "") continue;
safari.activate();
delay(0.1);
safari.windows[0].currentTab.url = aUrl;
console.log(`URL #${urlCount} ${aUrl}`);
if (wait4page(10)) {
const filename = `${urlCount}_`;
if (write2pdf(filename)) {
console.log(` #${urlCount} Write to PDF succeeded.`);
} else {
console.log(` #${urlCount} Write to PDF failed.`);
}
urlCount++;
}
}
// --- 関数定義 ---
function wait4page(repeatCount) {
while (repeatCount > 0) {
delay(0.1);
// Safariのドキュメントステータスを確認
const state = safari.doJavaScript('document.readyState', { in: safari.windows[0].currentTab });
if (state === "complete") return true;
repeatCount--;
}
return false;
}
function write2pdf(filename) {
app.setTheClipboardTo(filename);
safari.activate();
delay(0.5);
const fileMenu = safariProcess.menuBars[0].menuBarItems.byName("ファイル").menus[0];
const pdfMenuItem = fileMenu.menuItems.byName("PDFとして書き出す…");
// メニュー項目の確認
var retryCount = 0
while (!pdfMenuItem.exists() || !pdfMenuItem.enabled()) {
//console.log("wait for menu enabled")
if (retryCount > 1 && retryCount % 12 == 0) {
safariProcess.menuBars[0].menuBarItems.byName("表示").menus[0].menuItems.byName("ページを再読み込み").click();
console.log("reloaded!")
}
retryCount++;
delay(0.2)
}
pdfMenuItem.click();
delay(1); // シートが出るのを待つ
// 保存ボタンとシートの特定
let windowNo = -1;
let targetSheet = null;
for (let n = 0; n < safariProcess.windows.length; n++) {
const win = safariProcess.windows[n];
try {
const sheet = win.sheets[0];
if (sheet.exists() && sheet.splitterGroups[0].buttons.byName("保存").exists()) {
windowNo = n;
targetSheet = sheet;
break;
}
} catch (e) { }
}
if (windowNo === -1) {
const res = app.displayDialog("Button '保存' not found.", {
buttons: ["OK"],
defaultButton: "OK"
});
return false;
}
// ファイル名の入力と保存
safari.activate();
systemEvents.keyCode(123); // 左矢印キー
delay(0.5);
systemEvents.keystroke("v", { using: "command down" }); // 貼り付け
delay(0.5);
const saveButton = targetSheet.splitterGroups[0].buttons.byName("保存");
saveButton.click();
delay(0.5);
// 上書き確認ダイアログの処理
try {
const replaceSheet = targetSheet.sheets[0];
if (replaceSheet.exists()) {
replaceSheet.buttons.byName("置き換え").click();
}
} catch (e) {}
//閉じるのを待つ
while (targetSheet.exists()) {
delay(0.1);
console.log("wait for close sheet")
}
return true;
}
console.log("Completed.");
app.displayDialog("Mission Completed.", {buttons: ["OK"], defaultButton: "OK"});
return true;
})();
スクリプトエディタで繰り返し実行できるように、
グローバル変数を使わず、すべてを関数(ローカル変数)で記述しました。
これをしないと、applescript Error: SyntaxError: Can't create duplicate "variable-name"エラーになります。
✅実行例
スクリプトエディタで開いて実行するか、次のコマンドで実行します。
osascript url2pdf_jxa.scpt
- PDFファイル名は、ウインドウタイトルの先頭に 1〜 番号_を付与したファイル名になります
- すでに同名のファイルが存在する場合は、無条件に上書きします
- 注)スクリプトが終了するまで、UI操作をしないでください
✅出力されるPDF
メニュー → ファイル → "PDFとして書き出す…" で出力される PDFは、次のように縦に長い PDFとなります。
「印刷」でPDF化したものとは まったく異なります。
もし、印刷目的のPDFであれば、「印刷」でPDF化することをお勧めします。
以上

