Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

easyJParse v3

Posted on 9月 27, 2018 by Takaaki Naganoya

簡易的な日本語テキストのParse(辞書なし)を行うAppleScriptです。

英語などの言語では、文章中の各単語の間にスペース(” “)を入れるようになっており、

My name is Takaaki Naganoya.

文章を単語ごとに分割することがきわめて容易です。

words of "My name is Takaaki Naganoya."
--> {"My", "name", "is", "Takaaki", "Naganoya"}

一方、日本語の文章において単語は続けて記述するため、

私の名前は長野谷です。

これを単語ごとに切り分けるのは大変です。そのため、単語の辞書を手掛かりに文章中の単語を切り分けるのが普通です。

辞書を使って単語単位の切り分けを行う日本語形態素解析器

日本語テキストを単語(形態素)ごとに区分けするソフトウェアは日本語形態素解析器と呼ばれます。Chasen、Juman、MeCabなどが有名です。形態素解析のための巨大な辞書を用いて、地名ぐらいの固有名詞なら問題なくParseできることが普通です。各単語がどの品詞なのか、活用形はどうなっているかといった文法的な情報も管理しています。

たとえば、ApitoreのREST API経由でKuromojiを呼び出して形態素解析を行うと、

"警告音「Basso」を最大音量で鳴らす"
-->{{startTime:"1538006762864", tokens:{{partOfSpeechLevel1:"名詞", baseForm:"警告", pronunciation:"ケイコク", position:0, partOfSpeechLevel3:"*", reading:"ケイコク", surface:"警告", known:true, allFeatures:"名詞,サ変接続,*,*,*,*,警告,ケイコク,ケイコク", conjugationType:"*", partOfSpeechLevel2:"サ変接続", conjugationForm:"*", allFeaturesArray:{"名詞", "サ変接続", "*", "*", "*", "*", "警告", "ケイコク", "ケイコク"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"名詞", baseForm:"音", pronunciation:"オン", position:2, partOfSpeechLevel3:"一般", reading:"オン", surface:"音", known:true, allFeatures:"名詞,接尾,一般,*,*,*,音,オン,オン", conjugationType:"*", partOfSpeechLevel2:"接尾", conjugationForm:"*", allFeaturesArray:{"名詞", "接尾", "一般", "*", "*", "*", "音", "オン", "オン"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"記号", baseForm:"「", pronunciation:"「", position:3, partOfSpeechLevel3:"*", reading:"「", surface:"「", known:true, allFeatures:"記号,括弧開,*,*,*,*,「,「,「", conjugationType:"*", partOfSpeechLevel2:"括弧開", conjugationForm:"*", allFeaturesArray:{"記号", "括弧開", "*", "*", "*", "*", "「", "「", "「"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"名詞", baseForm:"Basso", pronunciation:"バッソ", position:4, partOfSpeechLevel3:"一般", reading:"バッソ", surface:"Basso", known:true, allFeatures:"名詞,固有名詞,一般,*,*,*,Basso,バッソ,バッソ", conjugationType:"*", partOfSpeechLevel2:"固有名詞", conjugationForm:"*", allFeaturesArray:{"名詞", "固有名詞", "一般", "*", "*", "*", "Basso", "バッソ", "バッソ"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"記号", baseForm:"」", pronunciation:"」", position:9, partOfSpeechLevel3:"*", reading:"」", surface:"」", known:true, allFeatures:"記号,括弧閉,*,*,*,*,」,」,」", conjugationType:"*", partOfSpeechLevel2:"括弧閉", conjugationForm:"*", allFeaturesArray:{"記号", "括弧閉", "*", "*", "*", "*", "」", "」", "」"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"助詞", baseForm:"を", pronunciation:"ヲ", position:10, partOfSpeechLevel3:"一般", reading:"ヲ", surface:"を", known:true, allFeatures:"助詞,格助詞,一般,*,*,*,を,ヲ,ヲ", conjugationType:"*", partOfSpeechLevel2:"格助詞", conjugationForm:"*", allFeaturesArray:{"助詞", "格助詞", "一般", "*", "*", "*", "を", "ヲ", "ヲ"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"名詞", baseForm:"最大", pronunciation:"サイダイ", position:11, partOfSpeechLevel3:"*", reading:"サイダイ", surface:"最大", known:true, allFeatures:"名詞,一般,*,*,*,*,最大,サイダイ,サイダイ", conjugationType:"*", partOfSpeechLevel2:"一般", conjugationForm:"*", allFeaturesArray:{"名詞", "一般", "*", "*", "*", "*", "最大", "サイダイ", "サイダイ"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"名詞", baseForm:"音量", pronunciation:"オンリョー", position:13, partOfSpeechLevel3:"*", reading:"オンリョウ", surface:"音量", known:true, allFeatures:"名詞,一般,*,*,*,*,音量,オンリョウ,オンリョー", conjugationType:"*", partOfSpeechLevel2:"一般", conjugationForm:"*", allFeaturesArray:{"名詞", "一般", "*", "*", "*", "*", "音量", "オンリョウ", "オンリョー"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"助詞", baseForm:"で", pronunciation:"デ", position:15, partOfSpeechLevel3:"一般", reading:"デ", surface:"で", known:true, allFeatures:"助詞,格助詞,一般,*,*,*,で,デ,デ", conjugationType:"*", partOfSpeechLevel2:"格助詞", conjugationForm:"*", allFeaturesArray:{"助詞", "格助詞", "一般", "*", "*", "*", "で", "デ", "デ"}, partOfSpeechLevel4:"*"}, {partOfSpeechLevel1:"動詞", baseForm:"鳴らす", pronunciation:"ナラス", position:16, partOfSpeechLevel3:"*", reading:"ナラス", surface:"鳴らす", known:true, allFeatures:"動詞,自立,*,*,五段・サ行,基本形,鳴らす,ナラス,ナラス", conjugationType:"五段・サ行", partOfSpeechLevel2:"自立", conjugationForm:"基本形", allFeaturesArray:{"動詞", "自立", "*", "*", "五段・サ行", "基本形", "鳴らす", "ナラス", "ナラス"}, partOfSpeechLevel4:"*"}}, endTime:"1538006762864", |log|:"", processTime:"0"}}

のようになります。これらのデータのうち、surface項目を抽出すると、

--> {"警告", "音", "「", "Basso", "」", "を", "最大", "音量", "で", "鳴らす", "。"}

となります。

辞書を使わずにトリッキーな方法で単語単位の切り分けを行う日本語パーサー

一方で、これらの日本語形態素解析器ほどの大規模なデータや機能が必要ない場合もあります。形態素解析のための辞書を持たず、単にそれっぽく単語ごとに区切ることができればよいという、「割り切った用途」に用いるもので、便宜上「日本語パーサー」と呼びます。単語っぽいものに分割することが目的であり、品詞のデータなどは取得できないのが普通です。

この種類のソフトウェアは、工藤 拓さんのTinySegmenterがあり、これをObjective-Cに移植したSuper compact Japanese tokenizer 「Tiny Segmenter」をCocoa Framework化してAppleScriptから呼び出し、テストしています。正規表現を用いて助詞などをピックアップして、それを手掛かりに単語切り分けを行うもので、そのサイズからは想像できないぐらいまっとうに単語に切り分けてくれます。

このTiny Segmenter(Objective-C版)をコマンド解釈用に使ってみたのですが、

--> {"警告音", "「Basso", "」", "を", "最大", "音量", "で", "鳴ら", "す"}

記号などがきちんと分離されなかったため、いまひとつ。自分でコマンド解釈用のParserを作ってみることにしました。

words ofの不完全さを補う簡易日本語パーサーeasyJParse

AppleScriptの「words of」は、前述のように英文であればスペースを区切り子として、文章の単語への分解を行ってくれます。

一方、日本語テキストに対して「words of」で単語分解処理を行うと、ながらく「文字種別の切り替え箇所で区切る」という気の狂ったような使えない処理が行われていました。その無意味さと使えなさをAppleのエンジニアにことあるごとに説明してきたのですが、一向に理解されず、相手にされてきませんでした。

# 冗談抜きで、Appleのエンジニアとは「戦いの歴史」しかありません。そして、そうして戦って勝ち取っていかないと機能の改善もバグの修正も何もないのであります(本当)

風向きが変わってきたのは、OS X 10.6のころ。このころから日本語テキストのwords ofの実行結果が形態素解析を行なっているような気がする動作を行うようになっており、何かに使えるような気がするものの……

 words of "警告音「Basso」を最大音量で鳴らす。"
 --> {"警告", "音", "Basso", "を", "最大", "音量", "で", "鳴らす"}

なぜか記号類などをすべて無視してしまうので、いまひとつ実用性がありませんでした。

そこで、基本的にはこの「words of」の演算結果を活かしつつ、オリジナルの文章と比較を行なって、欠損した記号類を補うことで簡易日本語parserとして利用できるのでは? と考えました。

set aTargName to "警告音「Basso」を最大音量で鳴らす。"
set aList to parseJ(aTargName) of me
--> {"警告", "音", "「", "Basso", "」", "を", "最大", "音量", "で", "鳴らす", "。"}

実際に作ってテストしてみたところ、自分が必要なコマンド解析ぐらいの目的には十分に使えることがわかりました。むしろ、単語切り分けについてはKuromojiと同じ結果が得られています。

しかも、辞書を持たないためコンパクトであり、実行速度もたいへんに高速で、このeasyJParseを組み込んだプログラムはREST APIの日本語形態素解析器を呼んだバージョンよりも明らかに高速化され、ネットワーク接続のない環境でも実行可能になりました。いいことづくめです。

easyJParseの制約事項

なお、easyJParseはすでに文章単位で分割されたテキストをコマンド解釈用に分解するため「だけ」に作ったものであり、長文を文章ごとに分割する機能は持っていません。別のプログラムやルーチンで文章ごとに分割してからeasyJParseで処理してください。

easyJParseは、日本語ユーザー環境における日本語テキストに対する「words of」の演算結果を利用しており、言語環境が日本語に設定していない環境で同様に演算できることは保証していません。
→ 一応、英語ユーザー環境で実行してみたら期待どおりの動作を行いました

当然のことながら、macOS専用です。一部Cocoaの機能を呼び出しているため、macOS 10.10以降で動きます(10.10では動作確認していませんけれども)。

AppleScript名:easyJParse v3
— Created 2018-09-26 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.5" — El Capitan (10.11) or later
use framework "Foundation"
use scripting additions

property NSArray : a reference to current application’s NSArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor

set aTargName to "警告音「Basso」を最大音量で鳴らす。"
set aList to parseJ(aTargName) of me
–> {"警告", "音", "「", "Basso", "」", "を", "最大", "音量", "で", "鳴らす", "。"}

–set aTargName to "JPEGファイルを50%にリサイズして、デスクトップの「AAA」フォルダに出力"
–set aList to parseJ(aTargName) of me
–> {"JPEG", "ファイル", "を", "50", "%", "に", "リサイズ", "し", "て", "、", "デスクトップ", "の", "「", "AAA", "」", "フォルダ", "に", "出力"}

on parseJ(aTargStr as string)
  copy aTargStr to tStr
  
  
set cList to characters of tStr
  
set wList to words of tStr
  
  
set cLen to length of cList
  
  
set w2List to {}
  
set w3List to {}
  
set aCount to 0
  
  
set lastPos to 0
  
  
repeat with i in wList
    set j to contents of i
    
    
set anOffset to offset of j in tStr
    
    
if anOffset is not equal to 1 then
      set aChar to character (lastPos + 1) of aTargStr
      
      
set the end of w3List to {wordList:aChar, characterList:{aChar}, startPos:(lastPos + 1), endPos:(lastPos + 1)}
    end if
    
    
set aLen to length of j
    
    
set w2List to w2List & (characters of j)
    
set startPointer to (anOffset + aCount)
    
set endPointer to (anOffset + aCount + aLen – 1)
    
    
set the end of w3List to {wordList:j, characterList:(characters of j), startPos:startPointer, endPos:endPointer}
    
    
set trimStart to (anOffset + aLen)
    
    
if trimStart > (length of tStr) then
      set trimStart to 1
    end if
    
    
set tStr to text trimStart thru -1 of tStr
    
    
set aCount to aCount + anOffset + aLen – 1
    
copy endPointer to lastPos
  end repeat
  
  
–句読点など。文末の処理
  
if endPointer is not equal to cLen then
    set the end of w3List to {wordList:tStr, characterList:(characters of tStr), startPos:(lastPos + aCount), endPos:aLen}
  end if
  
  
set bArray to sortRecListByLabel((w3List), "startPos", true) of me
  
set cArray to (bArray’s valueForKeyPath:"wordList") as list
  
  
return cArray
end parseJ

–リストに入れたレコードを、指定の属性ラベルの値でソート
on sortRecListByLabel(aRecList as list, aLabelStr as string, ascendF as boolean)
  set aArray to NSArray’s arrayWithArray:aRecList
  
set sortDesc to NSSortDescriptor’s alloc()’s initWithKey:aLabelStr ascending:ascendF
  
set sortDescArray to NSArray’s arrayWithObjects:sortDesc
  
set sortedArray to aArray’s sortedArrayUsingDescriptors:sortDescArray
  
return sortedArray
end sortRecListByLabel

★Click Here to Open This Script 

More from my site

  • 日本語簡易パーサーeasyJParse v5日本語簡易パーサーeasyJParse v5
  • easyJParse v4easyJParse v4
  • レコードのリストを複数Keyでソートレコードのリストを複数Keyでソート
  • PDFから指定ページ以降を削除PDFから指定ページ以降を削除
  • Finder上で選択中のMarkdown書類をファイル名で昇順ソート(A→Z)して、各書類のタイトル見出しを取得するFinder上で選択中のMarkdown書類をファイル名で昇順ソート(A→Z)して、各書類のタイトル見出しを取得する
  • CotEditorの最前面のテキストの日付フォーマットを変換するCotEditorの最前面のテキストの日付フォーマットを変換する
(Visited 291 times, 1 visits today)
Posted in Natural Language Processing Record Sort Text | Tagged 10.11savvy 10.12savvy 10.13savvy NSArray NSSortDescriptor | 7 Comments

7 thoughts on “<span>easyJParse v3</span>”

  1. 11/12/18
    6:40 PM
    2018年11月12日
    6:40 PM

    Reply

    Bayes推定による文章仕分け(Classifier) – AppleScriptの穴 says:

    […] らに単語の活用形をどうにかする必要があるはずですが、そこまで神経質にならずに簡易日本語パーサーで単語に分解し、助詞などを削除しデータとして与えることでそこそこの実用性は […]

  2. 12/14/18
    10:14 PM
    2018年12月14日
    10:14 PM

    Reply

    easyJParse v4 – AppleScriptの穴 says:

    […] 詳細な説明はこちら。 […]

  3. 12/24/18
    6:52 PM
    2018年12月24日
    6:52 PM

    Reply

    ぴよまるソフトウェアが選ぶ、2018年に書いた「価値あるScript」 – AppleScriptの穴 says:

    […] ・easyJParse v3 AppleScriptに備わっている「words of」による簡易形態素解析機能。なぜか途中の記号類をドロップするため、いまひとつ実用的ではありませんでしたが、本プログラムにより本 […]

  4. 10/22/19
    11:04 PM
    2019年10月22日
    11:04 PM

    Reply

    CotEditorの最前面のドキュメントの選択範囲を伏せ字に – AppleScriptの穴 says:

    […] easyJparseは日本語のコマンド解析用にでっちあげた作った超簡易形態素解析プログラムです。単語(形態素)ごとに分割しますが、品詞まではわかりません。コマンド解釈用ではあるもの […]

  5. 12/22/19
    11:34 AM
    2019年12月22日
    11:34 AM

    Reply

    CotEditor PowerPackのPiyomaru Software内での位置付け – AppleScriptの穴 says:

    […] 具体例を言うと、Tanzaku用に開発した コマンド解析用簡易日本語形態素エンジン「easyJParse」。これはAppleScriptだけで記述した80行ほどの規模の形態素解析プログラムです。これをコマンド解析用以外の、伏せ字処理のプログラムに使っています。 […]

  6. 6/26/21
    9:23 PM
    2021年6月26日
    9:23 PM

    Reply

    日本語簡易パーサーeasyJParse v5 – AppleScriptの穴 says:

    […] → easyJParse v3 → easyJParse v4 […]

  7. 4/10/25
    4:43 PM
    2025年4月10日
    4:43 PM

    Reply

    NaturalLanguage.frameworkを用いて日本語テキストの形態素解析を行う – AppleScriptの穴 says:

    […] 固有名詞を無視しまくるので、実用レベルにあるとはいえません。自分でAppleScriptで書いた簡易日本語パーサー「easyJParse」と処理結果が変わらないので、頑張ってNLTokenizerを使う意義はほ […]

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • CotEditorで2つの書類の行単位での差分検出
  • macOS 15, Sequoia
  • 指定のWordファイルをPDFに書き出す
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Numbersで選択範囲のセルの前後の空白を削除
  • メキシカンハットの描画
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AdobeがInDesign v19.4からPOSIX pathを採用
  • AppleScriptによる並列処理
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • Cocoa Scripting Course 続刊計画
  • macOS 14.xでScript Menuの実行速度が大幅に下がるバグ
  • AppleScript入門③AppleScriptを使った「自動化」とは?
  • NaturalLanguage.frameworkでNLEmbeddingの処理が可能な言語をチェック
  • Keynote/Pagesで選択中の表カラムの幅を均等割
  • Keynote、Pages、Numbers Ver.14.0が登場
  • macOS 15 リモートApple Eventsにバグ?
  • デフォルトインストールされたフォント名を取得するAppleScript
  • AppleScript入門① AppleScriptってなんだろう?

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (193) 14.0savvy (145) 15.0savvy (125) CotEditor (66) Finder (51) iTunes (19) Keynote (116) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (76) Pages (54) Safari (44) Script Editor (27) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • check sum
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC