如何使用不寻常的表格从选举网站上抓取数据

Posted

技术标签:

【中文标题】如何使用不寻常的表格从选举网站上抓取数据【英文标题】:How to scrape data from election website with unusual table 【发布时间】:2021-02-13 18:57:16 【问题描述】:

我正在尝试从选举网站上抓取一些数据,但不知道如何使用 BeautifulSoup 提取这些数据。

德克萨斯州选举结果 https://results.texas-election.com/contestdetails?officeID=1001&officeName=PRESIDENT%2FVICE-PRESIDENT&officeType=FEDERAL%20OFFICES&from=race

我尝试过的代码

import pandas as pd
from bs4 import BeautifulSoup

tx_url = 'https://results.texas-election.com/contestdetails?officeID=1001&officeName=PRESIDENT%2FVICE-PRESIDENT&officeType=FEDERAL%20OFFICES&from=race'


import urllib.request
local_filename, headers = urllib.request.urlretrieve(tx_url)

urllib.error.HTTPError:HTTP 错误 403:禁止

soup = BeautifulSoup(tx_url)

/home/server/pi/homes/woodilla/.conda/envs/baseDS_env/lib/python3.7/site-packages/bs4/init.py:357: 用户警告: “https://results.texas-election.com/contestdetails?officeID=1001&officeName=PRESIDENT%2FVICE-PRESIDENT&officeType=FEDERAL%20OFFICES&from=race” 看起来像一个 URL。 Beautiful Soup 不是 HTTP 客户端。你应该 可能使用类似请求的 HTTP 客户端来获取文档 URL,并将该文档提供给 Beautiful Soup。该文件到 美丽的汤。 % 解码标记

这是表格的样子:

【问题讨论】:

页面看起来是动态的。您是否检查过某些内容不是来自额外的 xhr? 【参考方案1】:

首先,您遇到的错误意味着您错误地使用了BeautifulSoup

您需要将来自 HTTP 客户端的响应传递给 BeautifulSoup,如下所示:

import requests
from bs4 import BeautifulSoup

url = "https://results.texas-election.com/races"

headers = 
    "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/86.0.4240.111 Safari/537.36",


response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, "html.parser")

其次,您不需要需要BeautifulSoup 来抓取该页面。一切都回到JSON。例如:

import requests

url = "https://results.texas-election.com/static/data/election/44146/246/Federal.json"

headers = 
    "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",

response = requests.get(url, headers=headers).json()

for race in response["Races"]:
    print(f"Results for race['N']")
    for candidate in race["Candidates"]:
        print(f"candidate['N'] - candidate['P']: Votes candidate['V'] - candidate['PE']%")
    print(f"Total votes: race['T']")
    print("-" * 80)

输出:

RESIDENT/VICE-PRESIDENT
ROQUE "ROCKY" DE LA FUENTE GUERRA - REP: Votes 7563 - 0.37%
BOB ELY - REP: Votes 3582 - 0.18%
ZOLTAN G. ISTVAN - REP: Votes 1447 - 0.07%
MATTHEW JOHN MATERN - REP: Votes 3512 - 0.17%
DONALD J. TRUMP (I) - REP: Votes 1898664 - 94.13%
JOE WALSH - REP: Votes 14772 - 0.73%
BILL WELD - REP: Votes 15824 - 0.78%
UNCOMMITTED - REP: Votes 71803 - 3.56%
Total votes: 2017167
--------------------------------------------------------------------------------
U. S.  SENATOR
VIRGIL BIERSCHWALE - REP: Votes 20494 - 1.06%
JOHN ANTHONY CASTRO - REP: Votes 86916 - 4.49%
JOHN CORNYN (I) - REP: Votes 1470669 - 76.04%
DWAYNE STOVALL - REP: Votes 231104 - 11.95%
MARK YANCEY - REP: Votes 124864 - 6.46%
Total votes: 1934047
--------------------------------------------------------------------------------
U. S. REPRESENTATIVE DISTRICT 1
JOHNATHAN KYLE DAVIDSON - REP: Votes 9659 - 10.33%
LOUIE GOHMERT (I) - REP: Votes 83887 - 89.67%
Total votes: 93546
--------------------------------------------------------------------------------
and so on ...

编辑:

要获取您提到的特定 URL 的数据,只需使用以下命令:

注意:这只是数据的一小部分,因为JSON 很大。我添加了用于转储整个 JSON 的代码,以便您可以按照自己的方式解析它。

import json

import requests

url = "https://results.texas-election.com/static/data/election/44144/108/County.json"

headers = 
    "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",

response = requests.get(url, headers=headers).json()


with open("county_results.json", "w") as output:
    json.dump(response, output, indent=4, sort_keys=True)

for v in response.values():
    for id_, race_data in v["Races"].items():
        print(race_data["C"])

示例输出:

'4250': 'id': 4250, 'N': 'KEN WISE (I)', 'P': 'REP', 'V': 0, 'PE': 0.0, 'C': '#E30202', 'O': 1, 'EV': 0, '6015': 'id': 6015, 'N': 'TAMIKA "TAMI" CRAFT', 'P': 'DEM', 'V': 0, 'PE': 0.0, 'C': '#007BBD', 'O': 2, 'EV': 0
'2966': 'id': 2966, 'N': 'BRENDA MULLINIX (I)', 'P': 'REP', 'V': 0, 'PE': 0.0, 'C': '#E30202', 'O': 1, 'EV': 0, '6224': 'id': 6224, 'N': 'JANET BUENING HEPPARD', 'P': 'DEM', 'V': 0, 'PE': 0.0, 'C': '#007BBD', 'O': 2, 'EV': 0
'2967': 'id': 2967, 'N': 'MAGGIE JARAMILLO (I)', 'P': 'REP', 'V': 0, 'PE': 0.0, 'C': '#E30202', 'O': 1, 'EV': 0, '3708': 'id': 3708, 'N': 'TAMEIKA CARTER', 'P': 'DEM', 'V': 0, 'PE': 0.0, 'C': '#007BBD', 'O': 2, 'EV': 0
and much, much more...

我是如何找到JSON的?

我检查了浏览器开发者工具的网络选项卡。 :)

【讨论】:

谢谢!这很好,但我想废弃我发布的包含更多数据分解的表格。有没有办法做到这一点? 您要准确刮取哪个表(选举)?因为有很多这样的。 这个特定的县拥有它,results.texas-election.com/… 所以特别是县的 pres/vice pres。 很奇怪,但我没有看到任何东西。只是一张空桌子。 非常感谢。这对我开始有很大帮助。现在将其移动到数据框并过滤我想要的内容。再次感谢!

以上是关于如何使用不寻常的表格从选举网站上抓取数据的主要内容,如果未能解决你的问题,请参考以下文章

使用名称从网站上抓取数据表

如何抓取 HTML 表格格式的数据?

如何使用python和beautifulsoup4循环抓取网站中多个页面的数据

如何从网站上从 ESRI Arcgis 抓取/提取数据?

使用RVest从网站抓取表格

VBA如何批量抓取数据