將 IMDb Top 250 排行榜轉為 CSV

IMDb Top 250 是許多喜愛電影人士的觀影參考。這份排行榜不知道多久更新一次,今天心血來潮,想要記錄一下目前的排行,然後隔一陣子再來比較。但是如果只是把網頁存下來,或是貼到 Evernote 去,到時候想要比較資料免不了又是一陣人力活,於是想到將排行榜的內容抓下來存為 CSV 檔,以後看是要做進一步的處理或分析都好辦。

所幸有 Python,抓網頁、分析 HTML,以及處理 CSV 檔這些事情不會太難應付。

/images/2012/2012-12-14-imdb-top250-csv.png

用來抓取網頁並轉存 CSV 的工具我放在 Gist 上,連結在此,程式不大,120 行左右,其中還有 20 幾行是直接從 Python 文件拿來用的,所以實際寫不到 100 行。

以下就程式碼做個簡單說明:

  1. 程式主要就 UnicodeWriter, IMDbTop250HTMLParser 這兩個 Class。
  2. UnicodeWriter 是從 Python Documentation 直接拿來用的 Class,作用是 unicode 編碼 csv 檔的輸出。
  3. IMDbTop250HTMLParser 則是繼承自 HTMLParser,繼承後要做的事就是覆寫 handle_starttag, handle_endtag, handle_data 這些個方法。比方說遇到 <tr> 就開始記錄一筆電影資料的 list,等到遇到 <\tr> 時就結束該筆記錄。

IMDb 這網站有多年歷史了,其 HTML 的撰寫也是相當原始,有許多不規範的地方。這也是撰寫這個小程式時主要遇到的困難點。例如在 IMDb Top 250 頁面的原始碼中有這麼一段:

<a href=http://www.imdb.com/games/guess/title:top_250?ref_=ch_qz>

注意,在屬性 href 之後的網址前後是沒有引號包夾的,這會造成 HTMLParser 解析時的錯誤。本來是想在 Parse 前把這個連結整個拿掉的,不過算了,這只是個小工具,不需要也不應該大費周章;所以用簡單的 hack 來解決就行。程式碼中的底下兩行有點突兀 (行號 13, 14),其實就是在幫上述連結加引號。

html = html.replace('href=http', 'href="http')
html = html.replace('ch_qz', 'ch_qz"')

另一個麻煩就是 IMDb 其實並不真正支援 Unicode,畢竟是那麼多年的老網站了。所以在英文字母之外的文字都會以 &#x1234; 之類的形式出現。例如電影 “8½”,這兩個字實際在 HTML 中的樣子是 8&#xBD;。這邊要將十六進位碼(在本例中為 “xBD”)轉為對應的 Unicode Char,實際的作法可以看代碼中的 UnicodeWriter.handle_charref() 這個方法。

程式完成後,接著只要執行程式,就會得到以日期為檔名的 CSV 檔,本文最上方的圖片就是成果。圖片中的表格是在 Finder 快速檢視的視窗,如果想要在 Finder 中按空白鍵就能檢視 CSV 檔的內容,可以參考這篇文章

喔,對了,寫這程式需要花多少時間?嗯…大概比寫這篇文章的時間還要少一點吧……