是工程师就自己简化流程,这种热血你我都有吧!?Windows铁人无脑自动发文带出30天最终大结局

终於,这天还是来了,是时候该做个了结,基於纯粹的好奇跟想炫技,想要认识Windows把她改造成自己喜欢的样子,这样的工程师到底正不正常,是第30天终究要解释的!(文末有结局,精华必看)


前情提要

第1天我们简单说了30天的目标,顺便示范了Windows备份和磁碟切割。
第2天到第14天我们介绍了所谓的登录档,知道他是如何运作跟操作,他的意义和清理,REG档的撰写我们也一并探讨。
第15天说了一些软件安装造成的系统影响。
第16,17天研究了一下Windows特殊资料夹的意义,批次档路径,系统权限等等。
第18天到24天我们学习事件检视器,讨论怎麽认识了解一个事件,甚至对日志档进行手动改写的操作。
第25-27天分别介绍了元件服务,工作排程器,效能监视器。
第28,29天提了命令提示字元和PowerShell的用法和指令稿的写法。

最後!来到了这一天,笔者想带给各位一个想法,Windows不再只是一个作业系统,我们不需要凡事都靠第三方软件才能达成,有时候用的习惯就忘了其实还有很多功能可以让我们来寻宝,为了证实这点,我就亲自挑战用PowerShell写个脚本来让铁人文章可以定时自动发文,全程使用Windows内建的功能,不用另外写Python,用最天真的想法去实现他。


确认目标

照着你最真实的需求去做!通常要自动发文,就是文章大致都完成了,不想为了每天发一篇文章而特地去记得然後去发文,而且为了看出预览状况,你一定先在铁文发文区打完文章的草稿了。
再来我们会使用自己平常的笔电,用着自己习惯的浏览器,在这里已经有大大帮我们看出,IT邦帮忙的cookie有效期限是30天,可以确保登入状态不会中途消失。

所以我们的现状大概会是,设定一个排程指向一个.ps1脚本,执行任务是把当天的草稿按下发表文章送出去。
(先偷偷透露成品给大家看)
Imgur


Coding前的思路

想像执行任务应该是先用浏览器开启文章列表,网址应该是:

https://ithelp.ithome.com.tw/users/<个人代码>/articles?page=<页码>

(其中page如果是第一页也不用加上问号後的page参数)

接着是我们如何判断今天要发的文章是哪一篇,在这里有个刚刚好的技巧,我们照顺序打完所有文章的草稿後,最後一篇草稿就是当天要发的,而发出去的新文章会往上叠,最後一篇草稿刚刚好还是下一篇要的发的,简单来说就是个伫列结构,FIFO原则,以下面这个例子来看,下一篇要发的草稿会一直维持在由上往下数来第7篇文章,我称这个数为todayArticleNumber
Imgur

笔者想到最简单方法就是我们设计指令一直去按Tab键去选中要发的文,但是因为中间每篇文章的Tag数不固定,所以也不能确定几次Tab键一定会到要发的草稿文上。

这时候我们去观察草稿文连结网址,发现他是以下形式:

https://ithelp.ithome.com.tw/articles/<文章代码>/draft

所以我们应该可以搜寻https://ithelp.ithome.com.tw/articles/.......开头的连结,往下数到一个特定的个数,就会是当天要发的草稿连结按钮,但是!後来发现这需要用到Invoke-WebRequest cmdlet,还需要登入状态所以要提取cookie等等就变得更复杂了。

为了符合我们的简单暴力美学,最後我想到一个可行替代方案,只要我们用ctrl+F搜寻特定关键字,这个关键字必须是每篇文章都包含的,例如由 <用户名> 分享这个词,就可以寻找到10个符合的结果,刚刚好对应10篇文章,这时候再由上往下数到第todayArticleNumber个结果,以这里的例子来看就是第7个,会刚刚好选到我们要发表的文章。
Imgur

不过我们用的由 <用户名> 分享这个关键字因为是在文章的结尾,当我们关闭搜寻功能後按下Tab键选中的会是下一篇文章连结,所以实际上我们要寻找第(todayArticleNumber – 1)个结果,中间就需要按(todayArticleNumber – 2)次Enter,这样後面按Tab才会到当天要发的文章连结,像在这个例子中我们需要按5次Enter选中第6篇文章的由 Zero皇 分享

在这中间我们还需要设定剪贴簿的功能,因为在搜寻框中打字会发生不确定现在是什麽输入法的问题,所以这部分的流程就是先把关键字由 <用户名> 分享放到剪贴簿,Ctrl+F搜寻,Ctrl+V贴上关键字,Enter todayArticleNumber – 2次到目标文章的前一篇文章结尾,接着按三次Tab选中搜寻框的叉叉,Enter关闭搜寻框。
Imgur
最後按Tab一次到目标文章,再Enter一次进入草稿编辑页。

接着我们到当天的草稿区後,如果要按到发表文章的按钮,直接Tab往下按最後会遇到内文区的文字框,变成输入Tab空格没办法继续选到页尾的发文钮,我们可以用个变通方法,那就逆向选取从网页末端选回来就好,Google一下会发现Shift+Tab是逆向选取的方法。

实际测试我们发现,当按到第11个逆向Tab(Shift+Tab)的时候,会选中储存文章旁边的三角形选项。
Imgur

下一个指令按Enter打开选单。
Imgur

再按一次Tab会选中我们最後的目标按钮。
Imgur

最後Enter出去应该就可以发文成功了!

所以全部的流程应该如下:

  1. 用浏览器开启文章列表网址。
  2. 设置关键字由 <用户名> 分享到剪贴簿。
  3. 按Ctrl+F搜寻。
  4. 按Ctrl+V贴上关键字。
  5. 按Enter todayArticleNumber – 2次到目标文章的前一篇结尾。
  6. 按三次Tab选中搜寻框的叉叉。
  7. 按Enter关闭搜寻框。
  8. 按一次Tab到目标文章
  9. 按Enter进入草稿编辑页。
  10. 逆向按11个Tab选中三角形按钮。
  11. 按Enter点开选单。
  12. 按一个Tab,这时候应该要选中发表文章的按钮。
  13. 最後按Enter会发出文章,测试时要确保前12步骤没有失误。

但是为了避免浏览器反应的速度跟不上一连串的按键指令,所以我们在必要时还是要暂停几秒的程序。

所以我们会需要四类指令,下面顺便给各位官网连结:

  1. 开启浏览器打开网页的指令
  2. 设置特定字串到剪贴簿的指令
  3. 各种按键输入的指令
  4. 暂停程序的指令

实作程序

首先我们打开Windows PowerShell ISE来写.ps1档~

  1. 用浏览器开启文章列表网址,建立$personCode跟$page两个变数来存草稿所在网页的资讯,不过powerShell的字串加上数字变数会被自动转型为全字串,所以两个变数有没有加双引号都可以。
#用浏览器开启文章列表网址
$personCode = "个人网址代码"
$page = "最後草稿所在页码"
START-Process chrome.exe "https://ithelp.ithome.com.tw/users/$personCode /articles?page=$page"
  1. 设置剪贴簿的指令是Set-Clipboard -Value <要被复制到剪贴簿字串>所以我们一样使用一个变数$keyWord来存放字串。
#把$keyWord复制到剪贴簿中
$keyWord = "由 <用户名> 分享"
Set-Clipboard -Value $keyWord
  1. 往後要进行按键输入的指令,通常前面会写两行先聚焦在特定视窗的指令,但上面我们用指令打开浏览器的时候焦点就在就在浏览器上了,所以下面这段主要是在测试的时候可以使用:
#聚焦当前视窗在<程序名>上
[void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
[Microsoft.VisualBasic.Interaction]::AppActivate("程序名")

下接着写一行载入System.Windows.Forms功能的指令,这是模拟按键事件需要的功能物件,後面就可以直接提取。

#载入按键输入必要物件System.Windows.Forms
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

再来是输入按键的指令,特殊键用{}表示,例如{TAB},{ENTER},Ctrl用^,Shift用+,不过使用组合键的时候有些程序会区分大小写需要测试才知道,例如Ctrl+F笔者发现用"^F"会无效,用"^f"则会成功:

#模拟按键输入
[System.Windows.Forms.SendKeys]::SendWait("要输入的字串")

然後为了让前面开启网页还有聚焦视窗有缓冲时间,必须先让程序暂停数秒,其指令为

#暂停程序<秒数>秒
Start-Sleep -Seconds <秒数>

所以第3步的程序如下:

#暂停3秒浏览器开启缓冲时间
Start-Sleep -Seconds 3
#聚焦当前视窗在chrome上
[void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
[Microsoft.VisualBasic.Interaction]::AppActivate("chrome")
#暂停1秒视窗聚焦缓冲时间
Start-Sleep -Seconds 1
#载入按键输入必要物件System.Windows.Forms
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
#模拟按键输入Ctrl+f
[System.Windows.Forms.SendKeys]::SendWait("^f")
  1. 按Ctrl+V贴上关键字,这个时候会浏览器会直接搜寻,所以再暂停1秒缓冲。
[System.Windows.Forms.SendKeys]::SendWait("^V")
Start-Sleep -Seconds 1
  1. 按Enter(todayArticleNumber - 2)次到目标文章的前一篇结尾,这个todayArticleNumber就必须提前先算好,一样用个变数存起来,而重复N次单按某个键可以用{键名 N}表示,但是N必须事先计算好,所以我们再建一个变数$EnterCount = $todayArticleNumber-2来代替N,就会像以下这样:
$todayArticleNumber = 7
$EnterCount = $todayArticleNumber-2
[System.Windows.Forms.SendKeys]::SendWait("{Enter $EnterCount}")

6.-9. 按三次Tab选中搜寻框的叉叉,再按Enter关闭搜寻框,再按一次Tab到目标文章,再按Enter进入草稿编辑页,最後再等待网页缓冲时间3秒。

[System.Windows.Forms.SendKeys]::SendWait("{TAB 3}")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
Start-Sleep -Seconds 3
  1. 逆向按11个Tab,用+代表Shift,跟着後面连按的11次Tab键,这时候要注意程序应该要选到三角形按钮,选错可能会选到隐藏的删除文章按钮,在测试的时候多注意。
#逆向按11个Tab键
[System.Windows.Forms.SendKeys]::SendWait("+{TAB 11}")

11.-12. 按Enter,再按一个Tab,这时候应该要选中发表文章的按钮,测试也要多注意。

[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
  1. 最後按Enter会发出文章,测试时要确保前12步骤没有失误。
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")

最後我们可以加上个贴心的设计,因为在程序被排程执行的时候使用者不能跟电脑互动否则步骤会乱掉,所以可以在第一行加上一句timeout /t 10,让程序暂停到数10秒後再开始,或按任意键可以直接开始,最前面再显示一行”铁人自动发文程序即将於10秒後启动,请暂停操作系统”就更帅了!

“铁人自动发文程序即将於10秒後启动,请暂停操作系统”
timeout /t 10

然後要用全Windows内建程序操作的话就把Chrome改成Edge登入即可,操作过程都一样,不过笔者建议用自己习惯的浏览器才是最好的,方法就是把chrome改成microsoft-edge:

START-Process microsoft-edge:"https://ithelp.ithome.com.tw/users/$personCode /articles?page=$page"

全部凑起来就会长这样,我们把需要设置的变数提到倒数秒数之前先载入,另外提醒,程序暂停的缓冲秒数因应个人电脑状况不同也要自行调配:

"铁人自动发文程序即将於10秒後启动,请暂停操作系统"

#个人设置区
$personCode = "20140925"
#改成个人网址代码
$page = "1"
#改成最後草稿所在页码
$todayArticleNumber = 7
#改成下篇要发的草稿在文章列表由上往下数来的第几篇文章
$keyWord = "由 Zero皇 分享"
#改成"由 <用户名> 分享"

timeout /t 10

#1.
#要用Edge则把"chrome.exe "改成"microsoft-edge:"
START-Process chrome.exe "https://ithelp.ithome.com.tw/users/$personCode/articles?page=$page"

#2.
Set-Clipboard -Value $keyWord

#3.
#暂停3秒浏览器开启缓冲时间
Start-Sleep -Seconds 3
#聚焦当前视窗在chrome上
#[void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
#[Microsoft.VisualBasic.Interaction]::AppActivate("chrome")
#暂停1秒视窗聚焦缓冲时间
#Start-Sleep -Seconds 1
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.SendKeys]::SendWait("^f")

#4.
[System.Windows.Forms.SendKeys]::SendWait("^V")
#暂停1秒搜寻缓冲时间
Start-Sleep -Seconds 1

#5.
$EnterCount = $todayArticleNumber-2
[System.Windows.Forms.SendKeys]::SendWait("{Enter $EnterCount}")

#6.-9.
[System.Windows.Forms.SendKeys]::SendWait("{TAB 3}")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
#暂停3秒网页开启缓冲时间
Start-Sleep -Seconds 3

#10.
[System.Windows.Forms.SendKeys]::SendWait("+{TAB 11}")
#确认选到三角形按钮

#11.-12.
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")

#13.
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
#确保前12步骤没有失误

Imgur

最後我们把他放进工作排程器,就完成每天自动执行的功能了,这部分可以参考工作排程器--Windows的忠实程序秘书这篇,设定完大概像这样:
Imgur
Imgur


30天最终大结局

其实这个想法很单纯天真,前後基本上只用了四种指令,就是用powerShell直接操作GUI介面,暴力找出我们要的连结然後全部用按键点进去而已,也不用提取cookie或是判断标签ID,说实在这支程序可能不耐用,或许一个官网改版就要修一次,但他符合一种,只要你想做就可以用最基本的方式做到的心态,想学就去学,身为工程师这种想要对自己电脑好一点的想法,去爱上自己独一无二的Windows很正常吧?

妄想对她优化对她Debug,改造成自己想要的样子,如果你还称得上她一声夥伴,油然而生的感情会让你跟她走上一辈子,解除软件生命周期的约束,超越系统的坚定,这样的妄想是一种熟悉感,一种踏实感,一种幸福感。

好比自行车手爱着他的自行车,我们也该对自己的Windows抱有期待和支持,一套Windows系统你至今用了多久,他还有无止尽的One Piece等你去找,期待你继续探索下去,对我这30天的内容有兴趣的话,都欢迎你在下方留言跟我讨论,Zero皇感谢看到这里的各位啦~ 後会有期罗!

Imgur

Imgur
参考资料:
https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/sendkeys-statement
https://stackoverflow.com/questions/3429863/sendkeys-ctrl-a-not-working
https://stackoverflow.com/questions/57053312/how-to-open-edge-using-powershell-variable


<<:  Day27 简易小键盘小实作2

>>:  [Python 爬虫这样学,一定是大拇指拉!] DAY24 - 实战演练:伪装

2022/1/2 更新

1.Grid_Optimizer: 原本使用4年资料回测,改成5年,00646改00662。 2.G...

Day 19 随机森林

今天我们要介绍的是随机森林,所谓的随机森林就是指将多个决策树组合而成并且加入随机的分配去训练资料,而...

Day25-jQuery的一点小转场_会打开的搜寻栏

今天写一个简单的搜寻栏样式 有时候会在navbar上看到那种搜寻键,按下去後搜寻栏会拉开变出可以打字...

[13th][Day1] 前言

今次参与战斗是为了挑战自我。 在生活中挤出时间,利用下班的时间好好充实自己。 在加入新团队後,con...

前端工程师也能开发全端网页:挑战 30 天用 React 加上 Firebase 打造社群网站|Day24 修改会员密码

连续 30 天不中断每天上传一支教学影片,教你如何用 React 加上 Firebase 打造社群...