最近努力学习新知识,在公司内网上阅读一些优秀文章,但是发现这些文章:是通过通过flash控件展示,并且不提供无法下载地址(类似《百度文库》)。一次忍了,两次再忍了,三次就无法忍受:都在我电脑上展示了,这么做就是恶心人了。。。。
于是花了大半天时间,使用mac上自带软件Automator,从零开始完成了自己的工具:《连续抓图导出PDF》。
实现原理:自动截屏、翻页=》merge生成PDF文档。(感兴趣的人,可以下载附件看看源码)
在写这个脚本过程中,本以为会很快,但是还是碰到了不少问题;于是就记录并分享出来。
首先:最基本用法,可以直接参考Automator帮助,本文章只写自认为容易忽略或者难点的几个地方。
变量新建就不说了;这里主要说变量再控件上使用,几种方法(有的方法只对部分控件有用):
当然你也可以,抛弃使用已存在的变量,直接通过下拉框选择一个“新建变量”。
最后,如果上面三种方法你尝试都不行的话,基本上可以宣告,那个是不支持变量的。
比如,LOOP的“次数”,是不支持变量的:
Automator脚本支持:shell脚本(bash、perl、python、ruby等)、appleScript、javascript几种,你可以选择不同的脚本来运行。
脚本和变量之间,是无法直接获取或设置的
– shell脚本
获取到的输入:只能是通过输入的一行一行的字符串
也即如果,想获取变量值的话,可以通过,“获得变量的值”控件来输出值,然后传递到脚本然后再读取。
如:下面是获取“页数”、“URL”、“临时文件夹”三个变量值到输出,然后传递给perl脚本。
– AppleScript脚本
AppleScript的输入不是一行一行的字符串,貌似是键值队(还不熟悉这块),结果没搞懂如何传递的变量——搞懂后,再补充。
于是我考虑的解决方案是:通过分隔符“|”将输入的多行转换成一行,然后在AppleScript进行反转。的确是有些trick -_-!——不过后来查资料发现,也有人这么整。
@input = ();
while (<>) {
$_=~s/(^\s*)|(\s*$)//g;
push(@input,$_);
}
print join "|" ,@input;
AppleScript代码:
on run input
set myArray to my theSplit((item 1 of input) as string, "|")
set outputPath to item 1 of myArray
set pagenum to item 2 of myArray as number
set myurl to item 3 of myArray
set tempDir to item 4 of myArray
return myArray
end run
on theSplit(theString, theDelimiter)
-- save delimiters to restore old settings
set oldDelimiters to AppleScript's text item delimiters
-- set delimiters to delimiter to be used
set AppleScript's text item delimiters to theDelimiter
-- create the array
--set theArray to every text item of theString
set theArray to text items of theString
-- restore the old setting
set AppleScript's text item delimiters to oldDelimiters
-- return the result
return theArray
end theSplit
脚本中的变量,是无法设置到脚本中,怎么办呢?其也只能通过脚本输出结果,然后“设定变量的值”控件,对变量进行设置。
- - 设置一个变量
注意:这里有一个问题,如果脚本输出的是多行,其实只把第一行字符串,赋值到“变量”中
但是如果要设置多个变量值,咋办?
于是又是一个trick方法来了,利用上面“只会把第一行赋值给变量”的机制,通过“漏斗”方式逐个对变量进行赋值:
如上图,依次对“导出路径”、“页数”等多个变量进行逐个复制。
其中perl代码作用是:过滤第一行字符串:
$count=0;
while(<>){
print $_ if $count >0 ;
$count = $count + 1 ;
}
Automator提供“录制”功能,位于右上角:
注意如果你使用录制功能,需要mac再偏好设置里,设置一下“允许Automator控制你的电脑”,这样在运行时才有用:
但是实际操作起来,我碰到了下面两个问题:
1、鼠标录制,总是不准
2、键盘录制,则永远也没有录制上去
第一个问题,我没有找到很好办法;最后没有使用;
第二个问题,不是录入,而是写代码,通过appleScript来实现:
on run {input, parameters}
--
set timeoutSeconds to 0
set uiScript to "keystroke \"a\" " --标注,注意这行代码
my doWithTimeout(uiScript, timeoutSeconds)
return input
end run
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"
" & uiScript & "
end tell"
exit repeat
on error errorMessage
if ((current date) > endDate) then
error "Can not " & uiScript
end if
end try
end repeat
end doWithTimeout
接下来,看看键盘操作(均是修改,标注的那一行)几种情况解决方案:
普通字符,比较简单,使用keystroke ,输入字符就可以,比如输入”a”字符:
set uiScript to "keystroke \"a\" "
对于一些特殊字符,没有特殊ASCII码,比如:上、下、左、右键。因此可以考虑另外一个通过“键值”(即操作系统对按键的虚拟值)来实现,key code :
比如:“右”按键的代码是:
set uiScript to "key code 124 "
当然,key code 也可以输入普通字符,如:
“a” 按键代码是:
set uiScript to "key code 0 "
“A”按键代码是:
set uiScript to "key code 0 using {shift down} "
mac系统的虚拟键值,可以通过终端命令执行下面命令查询到:
$ grep '^ *kVK' /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h|tr -d ,|while read x y z;do printf '%d %s %s\n' $z $z ${x#kVK_};done|sort -n
或者你直接查下“附1-key code 表”也行:
上两个方法,都可以配合组合键进行使用:
set uiScript to "key code 124 using {control down, option down, command down,shift down}" --control+option+command+right+shift
Automator对于系列处理动作的流程,制作非常简单,仅仅需要拖拽基本就可以实现。
但是在分支、循环等这种逻辑上,处理起来要复杂很多。 基本稍微复杂一点的都需要脚本配合才可以的。
Automator只提供了简单的“Loop”循环控件,这个循环控件可控执行很差,因为:
只能从脚本开头循环
循环策略支持:
A)次数/时间,但是无法通过变量控制
B)询问方式
试想一下,你就是需要从中间块循环,但是他非要从开头开始,你是无法选择的,这是个多么想哭的事情。
那么对于复杂的循环怎么处理?
Automator支持workflow的调用,因此如果你需要循环的话一种解决方案就是:将需要循环块的部分,写成workflow1,然后再主workflow通过脚本控制workflow1的循环。
这里实现主要有两个问题:
1、workflow之间的变量是无法共享的(至少现在我发现是这样的)。它也只能想字符串一样传递。
但是这个问题:上面脚本使用一节中的“多变量的赋值”方法可以解决。
2、如何脚本调用,workflow?
通过 do shell script cmd,进行执行cmd命令调用,但是这里有一个问题就是:命令执行是不等待结束立即返回的(实现方法是新起进程执行)——目前还没有找到能够等待返回的方法。
on run input
set myArray to my theSplit((item 1 of input) as string, "|")
set outputPath to item 1 of myArray
set pagenum to item 2 of myArray as number
set myurl to item 3 of myArray
set tempDir to item 4 of myArray
delay 10
set mycount to 1000 as number
repeat
run_workflow(tempDir & "/" & (mycount) & ".pdf", "/Users/xxxx/Desktop/test2/自动截频.workflow")
if pagenum ≤ 1 then
exit repeat
end if
set pagenum to pagenum - 1
set mycount to mycount + 1
--按下右键
set timeoutSeconds to 2
set uiScript to "keystroke (ASCII character 29) "
my doWithTimeout(uiScript, timeoutSeconds)
end repeat
delay 1
return myArray
end run
--执行workflow
on run_workflow(inputVars, workflowPath)
set {tid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, linefeed}
set theInputsList to inputVars as text
set AppleScript's text item delimiters to tid
set cmd to "automator -i '" & theInputsList & "' " & workflowPath
return do shell script cmd
end run_workflow
on theSplit(theString, theDelimiter)
-- save delimiters to restore old settings
set oldDelimiters to AppleScript's text item delimiters
-- set delimiters to delimiter to be used
set AppleScript's text item delimiters to theDelimiter
-- create the array
--set theArray to every text item of theString
set theArray to text items of theString
-- restore the old setting
set AppleScript's text item delimiters to oldDelimiters
-- return the result
return theArray
end theSplit
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"
" & uiScript & "
end tell"
exit repeat
on error errorMessage
if ((current date) > endDate) then
error "Can not " & uiScript
end if
end try
end repeat
end doWithTimeout
十进制 | 十六进制 | 按键 |
---|---|---|
0 | 0x00 | ANSI_A |
1 | 0x01 | ANSI_S |
2 | 0x02 | ANSI_D |
3 | 0x03 | ANSI_F |
4 | 0x04 | ANSI_H |
5 | 0x05 | ANSI_G |
6 | 0x06 | ANSI_Z |
7 | 0x07 | ANSI_X |
8 | 0x08 | ANSI_C |
9 | 0x09 | ANSI_V |
10 | 0x0A | ISO_Section |
11 | 0x0B | ANSI_B |
12 | 0x0C | ANSI_Q |
13 | 0x0D | ANSI_W |
14 | 0x0E | ANSI_E |
15 | 0x0F | ANSI_R |
16 | 0x10 | ANSI_Y |
17 | 0x11 | ANSI_T |
18 | 0x12 | ANSI_1 |
19 | 0x13 | ANSI_2 |
20 | 0x14 | ANSI_3 |
21 | 0x15 | ANSI_4 |
22 | 0x16 | ANSI_6 |
23 | 0x17 | ANSI_5 |
24 | 0x18 | ANSI_Equal |
25 | 0x19 | ANSI_9 |
26 | 0x1A | ANSI_7 |
27 | 0x1B | ANSI_Minus |
28 | 0x1C | ANSI_8 |
29 | 0x1D | ANSI_0 |
30 | 0x1E | ANSI_RightBracket |
31 | 0x1F | ANSI_O |
32 | 0x20 | ANSI_U |
33 | 0x21 | ANSI_LeftBracket |
34 | 0x22 | ANSI_I |
35 | 0x23 | ANSI_P |
36 | 0x24 | Return |
37 | 0x25 | ANSI_L |
38 | 0x26 | ANSI_J |
39 | 0x27 | ANSI_Quote |
40 | 0x28 | ANSI_K |
41 | 0x29 | ANSI_Semicolon |
42 | 0x2A | ANSI_Backslash |
43 | 0x2B | ANSI_Comma |
44 | 0x2C | ANSI_Slash |
45 | 0x2D | ANSI_N |
46 | 0x2E | ANSI_M |
47 | 0x2F | ANSI_Period |
48 | 0x30 | Tab |
49 | 0x31 | Space |
50 | 0x32 | ANSI_Grave |
51 | 0x33 | Delete |
53 | 0x35 | Escape |
55 | 0x37 | Command |
56 | 0x38 | Shift |
57 | 0x39 | CapsLock |
58 | 0x3A | Option |
59 | 0x3B | Control |
60 | 0x3C | RightShift |
61 | 0x3D | RightOption |
62 | 0x3E | RightControl |
63 | 0x3F | Function |
64 | 0x40 | F17 |
65 | 0x41 | ANSI_KeypadDecimal |
67 | 0x43 | ANSI_KeypadMultiply |
69 | 0x45 | ANSI_KeypadPlus |
71 | 0x47 | ANSI_KeypadClear |
72 | 0x48 | VolumeUp |
73 | 0x49 | VolumeDown |
74 | 0x4A | Mute |
75 | 0x4B | ANSI_KeypadDivide |
76 | 0x4C | ANSI_KeypadEnter |
78 | 0x4E | ANSI_KeypadMinus |
79 | 0x4F | F18 |
80 | 0x50 | F19 |
81 | 0x51 | ANSI_KeypadEquals |
82 | 0x52 | ANSI_Keypad0 |
83 | 0x53 | ANSI_Keypad1 |
84 | 0x54 | ANSI_Keypad2 |
85 | 0x55 | ANSI_Keypad3 |
86 | 0x56 | ANSI_Keypad4 |
87 | 0x57 | ANSI_Keypad5 |
88 | 0x58 | ANSI_Keypad6 |
89 | 0x59 | ANSI_Keypad7 |
90 | 0x5A | F20 |
91 | 0x5B | ANSI_Keypad8 |
92 | 0x5C | ANSI_Keypad9 |
93 | 0x5D | JIS_Yen |
94 | 0x5E | JIS_Underscore |
95 | 0x5F | JIS_KeypadComma |
96 | 0x60 | F5 |
97 | 0x61 | F6 |
98 | 0x62 | F7 |
99 | 0x63 | F3 |
100 | 0x64 | F8 |
101 | 0x65 | F9 |
102 | 0x66 | JIS_Eisu |
103 | 0x67 | F11 |
104 | 0x68 | JIS_Kana |
105 | 0x69 | F13 |
106 | 0x6A | F16 |
107 | 0x6B | F14 |
109 | 0x6D | F10 |
111 | 0x6F | F12 |
113 | 0x71 | F15 |
114 | 0x72 | Help |
115 | 0x73 | Home |
116 | 0x74 | PageUp |
117 | 0x75 | ForwardDelete |
118 | 0x76 | F4 |
119 | 0x77 | End |
120 | 0x78 | F2 |
121 | 0x79 | PageDown |
122 | 0x7A | F1 |
123 | 0x7B | LeftArrow |
124 | 0x7C | RightArrow |
125 | 0x7D | DownArrow |
126 | 0x7E | UpArrow |
http://download.csdn.net/detail/destiny_ac/8461453