印度古吉拉特州在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.