Safariで表示中のページのうち、テキストを選択中のキーワードを含む表をCSVファイルに書き出してNumbersでオープンするAppleScriptです。
–> Download tableExtractor Run-Only (Code-Signed Executable including Framework in its bundle)
実行前にSafariの「開発」メニューから、「スマート検索フィールドからのJavaScriptの実行を許可」「AppleEventからのJavaScriptの実行を許可」を実行しておく必要があります(実行済みの場合には必要ありません)。
▲Safariで表示中のページのうち、CSV書き出ししたい表のテキストを選択
▲本Scriptで表をCSVに書き出してNumbersでオープン
以前に作成した「Safariで表示中のPageの選択中の文字を含む表データを取得」Scriptがいい線を行っていた(あらかじめ表中のテキストを選択しておく、という前提条件がかったるいかと思っていたのに、そうでもなかった)ので、ありもののサブルーチンを追加して、表部分のHTMLからのタグ削除やCSV書き出しなどを行えるようにしました。
本Scriptは表データをCSV書き出しする必要はどこにもないのですが、Numbers v6.1に「表を新規作成して表のセル数を指定すると多くの場合にエラーになる」というバグがあるので、Numbersを直接操作してデータ出力させることはやっていません。
処理時間もさほどかからないので、表示中のページのすべての表オブジェクトをCSV化したり、表を選択するUIを実装して、「どの表を出力するか?」という選択処理をしてもいいかもしれません。
▲漫然とMacOS日本語で書き出ししたため文字化けしたもの(左)、UTF8を指定して書き出ししたために文字化けしなくなったもの(右)
途中でCSV書き出しした表データに文字化けが発生していたのですが、これはUTF8でファイル書き出ししていなかったためでした。
本Scriptは前バージョンよりもキーワードの検出処理をていねいに行なっています。各TableのHTMLに対してタグの除去を行なったうえでWebブラウザ上で選択中の文字列を含んでいるかどうかをチェックしています。
AppleScript名:tableExtractor.scptd |
— Created 2019-09-15 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "HTMLReader" –https://github.com/nolanw/HTMLReader property NSString : a reference to current application’s NSString property HTMLDocument : a reference to current application’s HTMLDocument property NSMutableArray : a reference to current application’s NSMutableArray tell application "Safari" set dList to every document –Sometimes "count every document"causes error if length of dList = 0 then return –Get URL tell front document set aURL to URL end tell –Get Selected Text set aRes to do JavaScript "var selObj = window.getSelection(); var selStr = (selObj).getRangeAt(0); unescape(selStr);" in front document if aRes = "" then return end tell set aRes to filterATableAndPaseCells(aURL, aRes) of me if aRes = false then display notification "I could not filter table data…" return end if –Save 2D List to temp CSV file on desktop folder set savePath to ((path to desktop) as string) & (do shell script "uuidgen") & ".csv" saveAsCSV(aRes, savePath) of me tell application "Numbers" activate open file savePath end tell on filterATableAndPaseCells(aURL, aKeyword) set aData to (do shell script "curl " & aURL) set aHTML to current application’s HTMLDocument’s documentWithString:(aData as string) –Table要素をリストアップ set eList to (aHTML’s nodesMatchingSelector:"table") –Table要素のうちSafari上で選択中の文字列を含むものをサーチ(指定データを含むものを抽出) set hitF to false repeat with i in eList set cellList to i’s children()’s array() set htmlSource to i’s serializedFragment() as string –HTML source set html2 to trimStrFromTo(htmlSource, "<", ">") of me set html3 to repChar(html2, return, "") of me if html3 contains aKeyword then set hitF to true exit repeat end if end repeat if hitF = false then return false –Count columns of Table Header set aTableHeader to (i’s nodesMatchingSelector:"tr")’s firstObject() set hList to aTableHeader’s nodesMatchingSelector:"th" set hStrList to {} repeat with i1 in hList set the end of hStrList to i1’s textContent() as string end repeat set hLen to length of hStrList –count columns –Acquire whole table body contents set aTableBody to (i’s nodesMatchingSelector:"tbody")’s firstObject() set bList to aTableBody’s nodesMatchingSelector:"td" set bbList to {} repeat with i2 in bList set the end of bbList to i2’s textContent() as string end repeat set tbList to makeList1DTo2D(bbList, hLen) of me return {hStrList} & tbList end filterATableAndPaseCells –1D Listを2D化 on makeList1DTo2D(orig1DList, aMax) set tbList to {} set tmpList to {} set aCount to 1 repeat with i3 in orig1DList set j to contents of i3 set the end of tmpList to j if aCount ≥ aMax then set aCount to 1 set the end of tbList to tmpList set tmpList to {} else set aCount to aCount + 1 end if end repeat return tbList end makeList1DTo2D on trimStrFromTo(aParamStr, fromStr, toStr) set theScanner to current application’s NSScanner’s scannerWithString:aParamStr set anArray to current application’s NSMutableArray’s array() repeat until (theScanner’s isAtEnd as boolean) set {theResult, theKey} to theScanner’s scanUpToString:fromStr intoString:(reference) theScanner’s scanString:fromStr intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:toStr intoString:(reference) if theValue is missing value then set theValue to "" theScanner’s scanString:toStr intoString:(missing value) anArray’s addObject:theValue end repeat if anArray’s |count|() = 0 then return aParamStr copy aParamStr to curStr repeat with i in (anArray as list) set curStr to repChar(curStr, fromStr & i & toStr, "") of me end repeat return curStr end trimStrFromTo on repChar(aStr, targStr, repStr) set aString to current application’s NSString’s stringWithString:aStr set bString to aString’s stringByReplacingOccurrencesOfString:targStr withString:repStr set cString to bString as string return cString end repChar –2D List to CSV file on saveAsCSV(aList, aPath) –set crlfChar to (ASCII character 13) & (ASCII character 10) set crlfChar to (string id 13) & (string id 10) set LF to (string id 10) set wholeText to "" repeat with i in aList set newLine to {} –Sanitize (Double Quote) repeat with ii in i set jj to ii as text set kk to repChar(jj, string id 34, (string id 34) & (string id 34)) of me –Escape Double Quote set the end of newLine to kk end repeat –Change Delimiter set aLineText to "" set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to "\",\"" set aLineList to newLine as text set AppleScript’s text item delimiters to curDelim set aLineText to repChar(aLineList, return, "") of me –delete return set aLineText to repChar(aLineText, LF, "") of me –delete lf set wholeText to wholeText & "\"" & aLineText & "\"" & crlfChar –line terminator: CR+LF end repeat if (aPath as string) does not end with ".csv" then set bPath to aPath & ".csv" as Unicode text else set bPath to aPath as Unicode text end if writeToFileUTF8(wholeText, bPath, false) of me end saveAsCSV on writeToFileUTF8(this_data, target_file, append_data) tell current application try set the target_file to the target_file as text set the open_target_file to open for access file target_file with write permission if append_data is false then set eof of the open_target_file to 0 write this_data as «class utf8» to the open_target_file starting at eof close access the open_target_file return true on error error_message try close access file target_file end try return error_message end try end tell end writeToFileUTF8 |
コンテンツ中の表示中のエリア座標を取得する – AppleScriptの穴 says:
[…] (1)表示中のURLを取得して処理 (2)表示中のコンテンツにJavaScriptを実行したりGUI Scripting経由で操作(特定要素をカウントしたりFormに値を入れたりボタンを押したり) (3)表示中のHTMLソースを取得して処理 (4)Webブラウザそのものの環境情報(Bookmarkや履歴など)にアクセスして処理 (5)選択中のテキストを取得して処理 (6)テキストを選択しておいて、その内容が該当する要素を抽出 […]