[Web/Python] 使用 mechanize 自動登入網站
原本是想要寫一個程式,可以每天自動下載痞客邦的備份檔,
因此在研究 web automation 的部分~
看到有人推薦使用 mechanize,這原本是用 Perl 寫的一個模組,
後來也移植到 python 上,因此就可以用 python 作 web 的 automation 了~
(當然還有很多種像是 Selenium、PhantomJS 等等)
很不幸地,我沒能成功地用 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 檔的話,就可以看到當時信箱的信件狀況:
下面把完整的範例程式列出來:
# 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 的囉~
4 thoughts on “[Web/Python] 使用 mechanize 自動登入網站”
請問為什麼我完全照著打他卻顯示 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
請問為什麼我完全照著打它卻顯示
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
pip insatll mechanize
應該是install…
版主回覆:(09/30/2016 05:04:35 PM)
感謝指正,已經修正囉~
我想問一下 如果以PYCHARM跑這些東西會顯示出甚麼呢 因為我覺得我跑出來的東西不符合另外可以跟樓主要個連絡方式嗎