Web Scraping

泰勞因為好奇,寫了一個 Python 腳本分析這次公投的結果,其實也稱不上是分析,只是很簡單的把同意票與不同意票的資訊抓下來,計算百分比而已。泰勞本身支持以民法保障同性婚姻,因此公投第14案是泰勞最關心的議題,本文會以中選會網頁之公投第14案投票結果作為 Web Scraping 的主要範例喔!

聲明:本文章沒有要討論公投議題的內容。

參考資料:
[The Hitchhiker's Guide to Python]HTML Scraping 

在開始之前,先安裝 lxml 和 requests 模組。
$ pip instal lxml requests

透過 requests.get 向網頁請求資料,並且確認伺服器回傳的狀態是否正常。
from lxml import html
import requests

page = requests.get('http://referendum.2018.nat.gov.tw/pc/zh_TW/08/m64000000100000000.html')
if page.status_code == requests.codes.ok:
    print 'OK!'

再來這步驟比較麻煩,先用網頁的 Inspector 找出你要的資訊所屬的 Elements。


找出對應的 Elements 之後,再用 html 模組和 xpath 函式來解析資料。
# Parse page by using html module
tree = html.fromstring(page.content)
# Create area list by using xpath function
area = tree.xpath('//td[@valign="bottom"]//text()')

# Create vote list by using xpath function
vote = tree.xpath('//tr[@class="trT"]/td/text()') 

印出來看看結果是否正確吧!area list 儲存的要是縣市區名稱,vote list 儲存的要是同意票數不同意票數、有效票數和無效票數。
print 'Area  : ', area[0]
print 'Agree  : ', vote[0]
print 'Disagree  : ', vote[1]
print 'Valid  : ', vote[2]
print 'Invalid  : ', vote[3]


現在可以取得重點資料了,接下來就自由發揮囉!泰勞擬定的目標是找出同意票大於不同意票的地方,從網頁來看,可以細分為縣市、區和投開票所,最小單位是投開票所,所以我們就來找出台北市裡同意公投第14案比例最高的投開票所吧!(泰勞懶惰所以直接無視無效票與投票權人數,只計算同意票與不同意票兩個資料)
from lxml import html
import requests


taipei_district_dic = {1:[527,644], 2:[644,786], 3:[1214,1402], 4:[786,919], 5:[1001,1097], 6:[919,1001],7:[1097,1214], 8:[1402,1564], 9:[455,527], 10:[305,455], 11:[142,305], 12:[1,142]}

print '===== Vote for Same-Sex Marriage ====='
for num in range(1,13):
    url_head = 'http://referendum.2018.nat.gov.tw/pc/zh_TW/08/m6300000'
    url_center = '0000'
    url_end = '.html'
    for n in range(taipei_district_dic[num][0],taipei_district_dic[num][1]):
        page = requests.get(url_head+str("%02d"%num)+url_center+str("%04d"%n)+url_end)
        if page.status_code == requests.codes.ok:
            tree = html.fromstring(page.content)
            area = tree.xpath('//td[@valign="bottom"]//text()')
            vote = tree.xpath('//tr[@class="trT"]/td/text()')
            # Ex: convert 1,561 into 1561
            agree = int(vote[0].replace(',',''))
            disagree = int(vote[1].replace(',',''))
            if agree > disagree:
                percentage = '{:.0%}'.format(float(agree)/float((agree+disagree)))
                print area[0] + ' NO.' + str(n) + ' Argee:' + str(agree) + ' Disagree:' + str(disagree) + ' ' + percentage

跑出來的結果顯示如下圖,原本以為會掛零呢!沒想到其實數量還不少,同意比例最高的地方出現在松山區的第 574 號投開票所,幾乎是 2 比 1。


Web Scraping 不難,但要用在有意義的地方才會突顯它的有趣。泰勞目前掃過了六都的資料,很意外的發現有幾個投開票所同意公投第14案的比例讓人難以置信呢!(灑花~)

 
GitHubGist:
https://gist.github.com/Kuanlin-Chen/d27089b611cce8fc363f1758acbcb557

留言

這個網誌中的熱門文章

程式語言常用之符號與詞彙 - 中英文對照

Repo 實用指令

什麼是 Bootloader?