使用 Mechanize 模擬網頁行為
不曉得大家有沒有想過使用程式來自動操作網頁行為呢?
一開始會對這個主題有興趣的原因很單純,我想要一支程式能自動每天早上和女朋友發訊息說「早安」,這樣除了能維持一個貼心男友的形象,還可以多睡一點不會被嫌冗,於是我開始投入對於 Mechanize 的研究,而這篇文章就會帶著大家走過完成一支自動打招呼程式的基本步驟。
我們可以想像,要完成「發送 FB 早安訊息給朋友」應該有以下步驟:
- 連上 Facebook 並登入自己的帳號
- 打開訊息夾,找到要發送訊息的朋友並點擊進入
- 輸入「早安」訊息並按下送出
那麼我們就一個個來吧!
首先創建我們的打招呼程式檔案:
# say_morning.rb
require "mechanize"fb_agent = Mechanize.new
fb_agent.get("https://m.facebook.com") do |page|
## some code...
end
一開始先引入 library,並使用 Mechanize class 建立一個物件,而這個物件就會成為你和網頁產生互動的代理人。
接著將此 agent 連線上 Facebook,通常我們打開瀏覽器瀏覽都是使用 GET,因此在這我們也使用 GET 到 https://m.facebook.com
,而為什麼不是常用的 https://www.facebook.com
呢?是因為前者是手機版的網頁,比較沒有繁雜的動態 JS 會擾亂我們要爬的東西,與後者相比相對單純的多。
在 block 裡面的 page
就是我們連線上的結果,偷偷用 pry 來看一下它是什麼:
可以看見 page
是一個 Mechanize::Page
的物件,而裡面的內容有 url, title, links 等等東西,這時候我們用無痕瀏覽器打開 https://m.facebook.com
來比對一下:
可以發現它們其實是一樣的東西,有一樣的 title, url, 建立新帳號等等,表示我們的程式成功連上 Facebook 了!
接著我們就要輸入帳號密碼並點下登入,仔細觀察這個 Mechanize::Page
物件可以發現它的下方有一個表單的物件 Mechanize::Form
:
在 fields 中有兩個的 name 分別為 email 以及 pass,這個其實就是讓我們輸入帳號密碼的欄位,因此我們可以用程式把它填上:
# say_morning.rb
require "mechanize"fb_agent = Mechanize.new
fb_agent.get("https://m.facebook.com") do |page|
page = page.form_with(method: "POST") do |form|
form.email = "example@gmail.com"
form.pass = "example_password"
end.submit
end
可以利用 .form_with()
來找尋.submit
方法來提交這個帳號密碼的表單,那麼提交後會得到什麼呢?
不太知道是什麼沒關係,我們就用無痕視窗來登入看看對照就知道了:
原來是問我們要不要儲存密碼,既然 Mechanize
那只有一個 button 可以選擇,那麼就加上 page = page.form_with(method: "POST").submit
就可通過這個頁面。
看到這裡,大家應該發現了一個基本的模式:用無痕查看頁面內容 → 使用 Mechanize
填入該頁面資料 → 送出表單,只要兩邊不斷對照就能一步步往前進。
接著我們就登入到個人動態時報頁面了,我們的目標是進入訊息收件夾中並找到要傳送訊息的朋友:
page.links.find { |link| link.text.start_with?("Message") }.click
page.links.find { |link| link.text.start_with?(<FriendName>) }.click
這裡我們要用到另一個技能:查看 links,並點擊。對於 Mechanize::Page
物件我們可以使用 .links
方法查看它所有的連結,再結合 .find
找到我們要點擊的連結關鍵字,好比說要先找到 “Message “,再找到朋友的名字進行點擊,而 Mechanize
也提供 .click
很直觀的方法做點擊的動作,因此 page = page.links.find { |link| link.text.start_with?("Message") }.click
就是完整的做了尋找特定連結、點擊它的動作,並且把結果存回 page
。
進入到聊天室頁面,那就是要傳送訊息了,把送出訊息這個動作當成在填表單就很好理解,幾乎跟送出帳號密碼的表單一樣:
page.form_with(method: "POST") do |form|
form.body = "早安"
end.submit
特別要注意的這個頁面較多,要找到對的表單
這樣就大功告成了,我們完成了一支可以送出「早安」訊息給朋友的程式
完整的程式碼為
# say_morning.rb
require "mechanize"
fb_agent = Mechanize.new
fb_agent.get("https://m.facebook.com") do |page|
# 輸入帳號密碼登入
page = page.form_with(method: "POST") do |form|
form.email = "example@gmail.com"
form.pass = "example_password"
end.submit # 通過詢問是否儲存密碼
page = page.form_with(method: "POST").submit
# 點擊訊息欄按鈕
page = page.links.find { |link| link.text.start_with?("Messages") }.click
# 點擊朋友名字
page = page.links.find { |link| link.text.start_with?(<FriendName>) }.click # 輸入訊息送出
page.form_with(method: "POST") do |form|
form.body = "早安"
end.submit
end
其實這是一個繁複的過程,需要有耐心的慢慢去看去比對,另外由於我們是直接去「爬」頁面上的內容,若是 Facebook 進行改版了,很有可能就會無法使用,必須重新修正程式碼。
除了送訊息以外,幾乎你能在網頁上做的事情都可以做到,好比說,自動邀請所有朋友到粉絲專頁按讚,原本必須一個個滑下去點擊,藉由程式去跑就能快速的節省許多時間!