印度古吉拉特州在12月的2017年進行了民意調查。執政黨 Bhartiya 人民黨 (人民黨) 設定了贏得150 席的目標, 但最終贏得了99。一些政治家評論說, 如果只有反對黨印度國民議會 (INC) 黨與其他反對黨結盟, 人民黨就不會獲勝。

現在, 在哪些席位中, 勝利保證金足夠狹窄, 使該公司亞軍和第二個亞軍候選人的結盟將使人民黨候選人輸掉?這就是人民黨候選人的獲勝幅度低于第三名候選人投票的選民。

該網站IndiaVotes提供了大量關于印度選舉的數據。為了回答我們的問題, 我們可以使用 Python 來刮掉相關的網頁, 處理和提取我們需要的數據。我們還可以將數據寫到 Excel 文件中, 這樣就可以使用諸如排序和篩選等方便的功能來獲得更多的視角。

我使用的 Python 庫是獲取網頁內容的 “請求”, “BeautifulSoup” 用于導航和分析 DOM 樹結構化數據, 以及用于創建 Excel 文件的 “openpyxl”。有許多教程解釋了 BeautifulSoup 的基本知識和用法。對于一個溫和流暢的介紹, 您可以通過 Jekaterina Kokatjuhha 簽出 “Python 的 Web 刮教程: 提示和技巧“。

在這里可以找到顯示古吉拉特2017結果的頁面。讓我們稱之為母版頁。在此頁上, 我們看到了表中的結果。

但它的摩擦是, 它使 AJAX 調用來獲取數據并加載它們。web 刮頁檢索 AJAX 返回的數據的方法有一些額外的步驟, 并在托德 Hayton 的文章中得到了很好的解釋, “用 Python 刮去 AJAX 頁面“。

關鍵步驟是計算 AJAX 請求所需的端點所要求的數據格式。同樣, 我們需要知道接收數據的格式。了解請求和響應數據格式很容易與瀏覽器的開發工具一起完成, 并簽出 “網絡” 選項卡。一旦我們知道了格式, 在我們的程序中, 我們只需要在請求中創建數據, 將它作為輸入發送到 AJAX 調用, 在收到響應后, 將它們轉換為合適的數據結構。第二個重要的事情是發送標題, ‘ X 請求-與 ‘: ‘ XMLHttpRequest ‘。有了這個, 我們發送一個 POST 請求。

我們的背景工作完成了嗎?不完全是。我們在母版頁上收到的數據不夠完整, 無法進行分析。雖然表中的數據是每個選區的選舉結果。我們只能看到獲獎候選人的姓名、黨派和保證金。

Master Page table

第二欄是一個超鏈接, 每個選區的詳細結果。例如, Abdasa 的 URL 是http://www.indiavotes.com/ac/details/29/37954/257/。讓我們把它稱為詳細頁面。瀏覽到此頁, 我們將看到表中顯示的 Abdasa 的結果。

Abdasa constituency detailed result為了了解如何提取數據, 我們檢查了兩頁中的表。對于母版頁, DOM 元素層次結構如下所示:

div : id = "m1", class = "mapTabData"
div : id = "DataTables_Tables_Table_0_wrapper", class = "dataTables_wrapper", role = "grid"
table : id = "DataTables_Table_0", class = "grid sortable dataTable"
tbody : role = "alert"
tr : class = "odd" or "even"
td : class="ta1" (second column)

導航結果很簡單。我們采用 id 為 “m1” 的元素, 獲取所有 “ta1” 類的 “td”。

對于詳細頁面, 元素層次結構為:

div : id = "m1", class = "mapTabData"
div : id = "DataTables_Table_0_wrapper", class="dataTables_wrapper" role = "grid"
table : id = "DataTables_Table_0", class = "grid sortable dataTable"
tbody : role = "alert"
tr : class = "bgR1 odd" or "even" or "odd"
td : class = "numberTable", "tar sorting_1", "ta1", "tar", "tar", "ta1" (six columns)

在這里, 導航也很簡單。我們采用 id 為 “m1” 的元素, 并獲取它下面的所有 “td”。一組五單元代表一個候選人的細節。

我用來舉行選舉結果的數據結構被稱為 “結果”。這是一本關于選區候選人的字典。字典里的鑰匙是地方 (選區)。該值是一個列表, 其中成員是列表, 每個列表中的五個值代表一個候選項。它的視覺描述是:

results data structure

現在, 我們有了我們的程序的所有組成部分, 我們設計的程序流:

  • 獲取母版頁。
  • 在內容中, 查找表 “m1″。
  • 獲取表中的所有行。
  • 抓住錨點元素和位置 (選區) 名稱。
  • 從錨點元素中提取 url。
  • 將位置和 URL 存儲為數組中的元組。
  • 遍歷數組, 即, 我們一次只選一個位置 (一個選區) 并調用其結果頁。
  • 在頁面內容中, 導航到表 “m1” 并抓取所有行。
  • 每行有五個單元格, 因此在讀取第五個單元格后, 將該行追加到我們的主要數據結構中。
  • 循環結束后, 即所有選區中所有候選者的數據都被提取, 處理主要數據結構。
  • 對于每個選區, 我們計算贏家的保證金。如果保證金小于第三名候選人投票的選票, 我們就有比賽;我們對那個選區感興趣。
  • 參加獲獎候選人的聚會, 并將選區名稱存儲在獨立的公司和人民黨的陣列中。
  • 用勝利保證金打印選區智者候選人信息。
  • 最后, 將整個數據 (完整選舉結果) 寫入 Excel 文件。

就這樣了我編碼的 Python 2.7 和運行的程序。您可以在GitHub上查看完整的程序。

GitHub 上, 您可以看到一個示例運行的輸出。

程序對我們的分析問題有什么說法?

有28個選區有密切的結果。其中17人是由人民黨贏得的。在其中的 15, 該公司是第二。在 15, Bahujan 社會黨贏取了二和民族主義國會黨贏取了三這仍然使人民黨擁有簡單的多數, 聯盟也不會擊敗它。

您還可以看到文件在此處生成的完整結果 Excel 文件。

Comments are closed.