Applescript с помощью Javascript и переданной переменной Applescript - PullRequest
1 голос
/ 23 мая 2019

Я написал скрипт, который автоматизировал создание продуктов на веб-сайте, которым я управляю.В моем процессе я загружаю изображения продуктов в формате JPEG и извлекаю ключевые слова, отмеченные тегом JPEG, чтобы добавить информацию о продукте.В этом процессе я использую Applescript для активации Safari и обрабатываю строку кода Javascript.Строка кода включает переменную, которая получена из скрипта оболочки Applescript.

Код ниже

tell application "Finder"
set sourceFolder to folder POSIX file "/Users/<username>/Desktop/Upload/Temp/HighRes/"
set theFiles to files of sourceFolder
set inputPath to "/Users/<username>/Desktop/Upload/Temp/"

end tell

repeat with afile in theFiles

set filename to name of afile

set fname to text 1 thru ((offset of "." in filename) - 1) of filename

--INPUT CODE TO BE LOOPED OVER BELOW--


--Add Image Keywords from Metadata--
try
    set pathVAR1 to "/Users/<username>/Desktop/Upload/Temp/HighRes/"

    set pathVAR2 to pathVAR1 & filename

    set myvar to do shell script "mdls -name kMDItemKeywords " & quoted form of pathVAR2

    set var1 to ((offset of "(" in myvar) + 1)

    set var2 to ((length of myvar) - 1)

    set myKeywords to ((characters var1 thru var2 of myvar) as string)

    --Inputs the Keywords from the Image Metadata--
    tell application "Safari"
        activate
        do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = \"" & myKeywords & "\";" in current tab of window 1
    end tell
end try

--END OF CODE TO BE LOOPED OVER--


end repeat

== Код конца ==

Проблема:

Приведенный ниже код не передает переменную myKeywords в Safari, ноесли я запускаю диалог, он появляется в диалоге.

do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = \"" & myKeywords & "\";" in current tab of window 1

Ответы [ 2 ]

1 голос
/ 06 июня 2019

Я пытался использовать обратные пометки (`), предложенные CJK, но это не сработало для меня.Основная проблема, которая была поднята, заключалась в том, что kMDItemKeywords возвращал экранированные символы.

Heart,
Studio,
Red,
\"RF126-10.tif\",
Tree,
\"Heart Tree\",
occasion,
Farm,
birds,
\"Red Farm Studio\",
\"all occasion\",
all

Мне удалось избавиться от экранированных символов с помощью следующего:

NEW CODE

set myKeywords to do shell script "echo " & quoted form of myKeywords & " | tr -d '[:cntrl:]'| tr '[:upper:]' '[:lower:]' | tr -d '\"'"


ОБНОВЛЕННЫЙ КОД ДЛЯ JAVASCRIPT

--Inputs the Keywords from the Image Metadata--
tell application "Safari"
    activate
    do JavaScript "document.getElementById('ctl00_cphMainContent_txtKeyWords').value = '" & myKeywords & "';" in current tab of window 1
end tell


РЕЗУЛЬТАТ

--> "    heart,    studio,    red,    rf126-10.tif,    tree,    heart tree,    occasion,    farm,    birds,    red farm studio,    all occasion,    all"
1 голос
/ 24 мая 2019

У меня нет конкретного решения, которое определенно решит вашу проблему, но у меня есть ряд замечаний по поводу вашего сценария с рекомендациями о том, как его можно изменить для повышения его скорости, надежности и соблюдения принципов наилучшей практики. .

  1. Избавьтесь от этого try блока. Вы не представляете, что происходит в вашем скрипте, когда что-то идет не так, если вы маскируете ошибки с ненужным перехватом ошибок. Единственная строка, которая должна быть заключена в try...end try, это do shell script, но вставляйте ее только тогда, когда вы знаете, что ваш код работает. В общем, следует использовать только блоки try:

    • когда ваш сценарий может выдать ошибку, которая полностью предсказуема и объяснима , и вы понимаете причины, по которым и при каких условиях возникает ошибка, позволяющая реализовать эффективный метод обработки ошибок;
    • вокруг наименьшего возможного количества строк кода, в которых возникает ошибка, оставляя все строки кода, существование которых не зависит от результата оператора, подверженного ошибкам (с); * 1 028 *
    • после того, как ваш сценарий был написан, протестирован и отлажен, где размещение блока (ов) try больше не служит для принудительного продолжения выполнения сценария после неудобной ошибки неизвестного происхождения, но имеет явное и четко определенная функция для выполнения в гармонии с вашим кодом, а не против него.
  2. Как общее правило в AppleScript, не используйте Finder для выполнения операций файловой системы, если вы можете избежать этого: он медленный и блокируется во время выполнения операций, то есть вы можете ' T взаимодействовать с GUI в течение этого времени. Вместо этого используйте Системные события . Это безликое приложение, которое не остановит работу других вещей при выполнении задачи; это быстро, в контексте AppleScript и, в частности, Finder , и оно не склонно к тайм-ауту настолько, как Finder ; он обрабатывает пути posix изначально (, включая расширение тильд), без какого-либо принуждения, необходимого при использовании POSIX file; он возвращает alias объекты, которые являются универсальным классом файловых объектов, которые понимает каждое другое приложение с поддержкой скриптов.

    В нескольких случаях Finder по-прежнему необходим. Системные события не может reveal файл; и при этом он не может получить выбранные вами файлы в Finder . Но достаточно просто Finder получить selection как alias list, а затем переключиться на Системные события , чтобы выполнить фактическую обработку файлов в этом списке.

  3. Это любопытно:

    set filename to name of afile
    set fname to text 1 thru ((offset of "." in filename) - 1) of filename
    

    Правильно ли я думаю, что fname намеревается содержать только часть имени базового файла в имени файла, и эта операция предназначена для удаления расширения? Это довольно хорошая первая попытка, и она отлично подходит для использования text здесь для упорядочивания компонентов строки, а не characters. Но это, конечно, в конечном итоге обрезает намного больше, чем просто расширение файла, если имя файла содержит более одного ".", что не редкость.

    Одним из способов безопасной кастрации конца имени файла является использование text item delimiters:

    set filename to the name of afile
    set fname to the filename
    
    set my text item delimiters to "."
    if "." is in the filename then set fname to text items 1 thru -2 of the filename as text
    

    Затем вы должны быть внимательны или сбрасывать text item delimiters после этого, иначе будут последствия, если вы попытаетесь объединить строки вместе.

    Другим способом прерывания расширения без использования text item delimiters является сканирование строк, когда вы перебираете символы строки, выполняя операции или тесты по ходу работы и достигая желаемого результата. Это быстрее, чем кажется, и мощный метод для очень сложного поиска строк и манипуляций:

    set filename to the name of afile
    set fname to the filename
    
    repeat while the last character of fname ≠ "."
        set fname to text 1 thru -2 of fname
    end
    
    set fname to text 1 thru -2 of fname
    

    Вы также можете получить свойство name extension файла, получить его длину и удалить (1 + that) много символов в конце имени файла. Существует множество способов достижения того же результата.

  4. Это неправильно в данном конкретном случае:

    set myKeywords to ((characters var1 thru var2 of myvar) as string)
    

    characters создает list, который затем необходимо объединить обратно в string, и это небезопасно, если вы не уверены, на что установлен text item delimiters. Поскольку вы не указали на это в своем скрипте, для следует установить в пустую строку, что приведет к объединению символов обратно в слова, что приведет к ожидаемому результату. Однако это не может быть так, если, скажем, вы выполнили первую технику кастрации расширений файлов и пренебрегли установкой text item limiters назад - тогда результирующая строка будет иметь период между каждой отдельной буквой.

    Как политика в AppleScript (которую вы лично можете придерживаться или игнорировать), некоторые считают ее плохой формой, если вы выполняете операции приведения списка к строке без , сначала устанавливая text item delimiters в окончательное значение.

    Но вам не нужно делать это здесь, потому что вместо characters используйте text:

    set myKeywords to text var1 thru var2 of myvar
    
  5. Вы выполняете команду оболочки, которая выглядит следующим образом: mdls -name kMDItemKeywords <file>, а затем две строки AppleScript, которые следуют неловко, пытаются обрезать начальные и конечные скобки вокруг текстового представления массива bash. Вместо этого вы можете включить флаг -raw для mdls, что упрощает вывод, удаляя для вас имя ключа. Это тогда помещает круглые скобки как самые первые и самые последние символы; однако, так как в выводе также есть множество мертвых пробелов, вы можете также получить bash, чтобы выполнить всю очистку за вас:

    mdls -raw -name kMDItemContentTypeTree <file> | grep -E -io '[^()",[:blank:]]+'
    

    Это игнорирует круглые скобки, двойные кавычки, запятые и пробелы, поэтому все, что вы получите, - это список ключевых слов, по одному на строку, без лишнего багажа. Если вам нужно их разбить на части, вы можете установить переменную the paragraphs of для вывода команды do shell script, которая разбивает текст на строки, помещая каждое ключевое слово в список. Но здесь кажется, что вам нужен текст, и он не против того, чтобы он был мультилинейным.


Когда я начал писать этот ответ, у меня не было ни малейшего представления о том, что стало причиной конкретной проблемы, которая привела вас сюда. Изучив детали того, как mdls форматирует вывод, я вижу, что проблема в том, что строка myKeywords будет содержать кучу двойных кавычек, и вы окружили размещение сущности myKeywords в вашем выражении JavaScript с двойными кавычками. Все эти кавычки экранируются одинаково и только один раз только в среде AppleScript, но не в среде JavaScript, что приводит к тому, что каждая соседняя двойная кавычка выступает в качестве пары открытия-закрытия. Я запустил аналогичную команду в bash, чтобы получить массив значений (kMDContentTreeType), а затем обработал текст так, как это делает AppleScript, прежде чем открыть консоль JavaScript в моем браузере и вставить ее, чтобы проиллюстрировать происходящее:

JavaScript console

Все, что в красном, содержится внутри строки; поэтому все остальное принимается в качестве идентификатора или объекта JavaScript (или это может быть, если испорченные кавычки не испортят синтаксис, а затем приведут к неопределенной строке, которая по-прежнему ожидает пару последних кавычек с *. 1141 *

Я думаю, что решение состоит в том, чтобы использовать символ продолжения "\" для обратной совместимости со старыми браузерами: так что вам нужно, чтобы каждая строка (кроме последней) добавлялась с обратной косой чертой, и вам нужно изменить пару двойных кавычек, окружающих значение myKeywords в вашем выражении JavaScript, на пару одинарных кавычек. В более новых браузерах вы можете отказаться от головной боли от добавления меток продолжения к каждой строке и вместо этого заменить пару внешних двойных кавычек на пару обратных символов (`) вместо этого:


❌'This line throws 
an EOF error in
JavaScript';


✅'This line is \
processed successfully \
in JavaScript';


✅`This line is also
processed successfully
in JavaScript`;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...