[Web/Python] 使用 mechanize 自動登入網站

[Web/Python] 使用 mechanize 自動登入網站

原本是想要寫一個程式,可以每天自動下載痞客邦的備份檔,

因此在研究 web automation 的部分~

看到有人推薦使用 mechanize,這原本是用 Perl 寫的一個模組,

後來也移植到 python 上,因此就可以用 python 作 web 的 automation 了~

(當然還有很多種像是 SeleniumPhantomJS 等等)

 

很不幸地,我沒能成功地用 mechanize 登入痞客邦… 問題還在找…

不過倒是可以用來登入 Yahoo!奇摩,因此就用這個來當範例吧~

 

其他參考資料:Emulating a Browser in Python with mechanize

 

1. 安裝 mechanize

用 easy_install 或 pip 就可以安裝 python 版的 mechanize:

easy_install mechanize
pip install mechanize

 

裝好之後,用 python interpreter 確定一下可以 import mechanize 這個 module:

testuser@localhost ~ $ python
Python 2.7.6 |Anaconda 1.9.1 (x86_64)| (default, Jan 10 2014, 11:23:15)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import mechanize
>>>

 

接下來就可以開始用 mechanize 來作 automation 了~

 

2. 建立 Browser 物件並作初始化設定

mechanize.Browser() 可以建立一個 Browser 物件,用來瀏覽網頁~

下面用到了 set_handle_robots(False) 代表不理會網站的 robots.txt…

有些網站會要求機器人不能來瀏覽,這邊設成 False 的話就會忽略網站的設定,

(不過當然這樣子是不太好的,要衡量一下)

import mechanize
br = mechanize.Browser()
br.set_handle_robots(False)

 

接著可以打開一些除錯用的設定,幫忙在開發過程中 debug:

br.set_debug_http(True)
br.set_debug_responses(True)
br.set_debug_redirects(True)

 

另外加上 User-Agent 的設定~

這是因為預設的 User-Agent 是 Python-urllib/2.7,部分網站可能會擋,

因此把它改成 Chrome 的 User-Agent:

# Add User-Agent
br.addheaders = [("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36")]

 

3. 用 Browser 物件登入 Yahoo! 網站

執行 open() 可以瀏覽一個 URL,回傳值是一個 response 物件~

不過不特別接回傳值也沒關係,可以用 br.response() 拿到同樣的 response 物件:

# Browse to login page
br.open('https://login.yahoo.com/config/login')

 

接下來要填帳號密碼之前,必須讓 mechanize 知道要對哪個表單做事~

這邊就要用 select_form() 這個函式來指定~

這邊如果知道表單的名稱,可以用 name=xxx 的方式指定,

不過如果表單沒有名稱的話,通常就是用 nr=yyy 的方式,

nr 代表的是第幾個表單 (從 0 開始)~

因為 Yahoo! 登入這邊只有一個表單,因此用 nr=0 就可以了:

# Select login form
br.select_form(nr=0)

 

如果表單有很多個,br.forms() 會包含所有的表單,

因此一個可能的做法是去 br.forms() 裡面一個個找,

看看哪個 form.action 是你想要的,例如:

# Select login form
form_index = [form_index for (form_index, form) in enumerate(br.forms()) if "login" in form.action][0]
br.select_form(nr=form_index)

 

接著要填入帳號密碼的部分,要知道表單裡對應的欄位是什麼名稱,

像是用 Chrome 按右鍵 > Inspect Element,

就可以看到 Yahoo 登入頁的欄位分別是 username 和 passwd,

用 br[欄位名稱] 就可以取得/填入值,然後用 br.submit() 送出表單:

# Fill in username and password, submit
br["username"] = "testuser"
br["passwd"] = "this is not my password"
br.submit()

 

4. 跳轉至信箱網頁並讀取信件

在上面的 br.submit() 之後,用 br.response().get_data() 可以取得網頁內容,

注意到網頁內容就是使用者登入後 Yahoo! 的首頁,右上方有信箱的連結~

可以用 br.links() 取得網頁中所有的連結,

找到要用的連結之後,執行 follow_link() 就可以跑到連結指到的網頁了:

# Find out the link to mail
link_mail = [l for l in br.links() if l.url.startswith("http://mail.yahoo.com")][0]
# Browse to mail page
br.follow_link(link_mail)

 

現在已經到了信箱網頁,因此 br.response().get_data() 存的就是信箱網頁的內容~

可以依照需求決定要如何處理它的內容,這邊只簡單把網頁存成 htm 檔案:

with open("output.htm", "w") as f:
f.write(br.response().get_data())

 

用瀏覽器開啟這 htm 檔的話,就可以看到當時信箱的信件狀況:

Screen Shot 2015-01-13 at 下午11.00.56  

 

下面把完整的範例程式列出來:

# coding=utf-8
import mechanize
br = mechanize.Browser()
br.set_handle_robots(False)
br.set_debug_http(True)
br.set_debug_responses(True)
br.set_debug_redirects(True)
# Add User-Agent
br.addheaders = [("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36")]
# Browse to login page
br.open('https://login.yahoo.com/config/login')
# Select login form
br.select_form(nr=0)
# Fill in username and password, submit
br["username"] = "testuser"
br["passwd"] = "this is not my password"
br.submit()
# Find out the link to mail
link_mail = [l for l in br.links() if l.url.startswith("http://mail.yahoo.com")][0]
# Browse to mail page
br.follow_link(link_mail)
with open("output.htm", "w") as f:
f.write(br.response().get_data())

 

以上就是利用 mechanize 作 web automation 的基本過程~

mechanize 的一個缺點是,如果碰上 JavaScript 的話,

就得自己找出 JavaScript 做的事情,然後操作 mechanize 讓它模擬那動作,比較麻煩~

對於簡單的網頁操作則是比較 OK 的囉~

 

 

(本頁面已被瀏覽過 2,442 次)

4 thoughts on “[Web/Python] 使用 mechanize 自動登入網站

  1. 請問為什麼我完全照著打他卻顯示 br.select_form(nr = 0) 這邊出錯QAQ
    跟我用python 2.7.10 有關係嗎
    版主回覆:(06/25/2015 05:31:05 AM)
    看來像是 Yahoo 的這一頁有一些 Unicode 字元,
    導致預設的 python 是不支援的…
    可能要自己重新 build python 來打開 ucs4 的開關:
    ./configure –enable-unicode=ucs4 && make
    參考來源:http://wordaligned.org/articles/narrow-python

  2. 請問為什麼我完全照著打它卻顯示
    Traceback (most recent call last):
    File "login.py", line 26, in <module>
    link_mail = [l for l in br.links() if l.url.startswith("http://mail.yahoo.co
    m")][0]
    IndexError: list index out of range

  3. pip insatll mechanize
    應該是install…
    版主回覆:(09/30/2016 05:04:35 PM)
    感謝指正,已經修正囉~

  4. 我想問一下 如果以PYCHARM跑這些東西會顯示出甚麼呢 因為我覺得我跑出來的東西不符合另外可以跟樓主要個連絡方式嗎

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料