You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:基于Network-Fetch/XHR抓取Asmbcd1-200的2018选举候选人投票数据

Karnataka 2018州议会选举数据抓取修正方案

现有代码的核心问题

  • 错误使用GET请求调用ASMX WebService接口:这类接口通常要求POST请求,并携带指定参数
  • 未传递关键参数:缺少选区编码Asmbcd(1-200)和选举年份(2018)的必要参数
  • 解析逻辑错误:ASMX接口返回的是包裹结构化数据的XML(而非直接HTML表格),直接用BeautifulSoup解析原始响应会失败

修正后的实现方案

关键调整点

  1. 改用POST请求,匹配接口要求的参数格式
  2. 循环遍历1-200的Asmbcd值
  3. 先解析ASMX返回的XML,提取内部的HTML表格后再处理数据
  4. 加入错误处理与数据持久化(保存为CSV)

完整代码实现

import requests
import json
import csv
from bs4 import BeautifulSoup
import time

# 目标接口地址
API_URL = "https://kgis.ksrsac.in/election/Election.asmx/GetPollingStationCandidateVotes"

# 请求头(从浏览器Network面板复制,确保请求合法性)
HEADERS = {
    "Content-Type": "application/json",
    "Referer": "https://kgis.ksrsac.in/election/AssemblyEng.aspx",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

# 初始化CSV文件保存数据
with open("2018_karnataka_election_results.csv", "w", newline="", encoding="utf-8") as csv_file:
    writer = csv.writer(csv_file)
    writer.writerow(["选区编码(Asmbcd)", "候选人姓名", "所属政党", "得票数"])

    # 遍历1到200的选区编码
    for asmbcd in range(1, 201):
        try:
            # 构造请求参数(匹配接口要求的格式)
            payload = json.dumps({
                "Asmbcd": str(asmbcd),
                "Year": "2018"
            })

            # 发送POST请求,加入延迟避免反爬
            time.sleep(1)
            response = requests.post(API_URL, headers=HEADERS, data=payload)
            response.raise_for_status()  # 捕获HTTP请求错误

            # 解析ASMX返回的XML数据,提取内部的HTML表格
            xml_soup = BeautifulSoup(response.text, "xml")
            table_html = xml_soup.find("GetPollingStationCandidateVotesResult").text
            table_soup = BeautifulSoup(table_html, "html.parser")

            # 定位目标表格并提取数据
            data_table = table_soup.find("table", id="GridData")
            if not data_table:
                print(f"选区 {asmbcd}: 无有效数据")
                continue

            # 遍历表格行(跳过表头行)
            for row in data_table.find_all("tr")[1:]:
                cells = row.find_all("td")
                if len(cells) >= 3:
                    candidate = cells[0].text.strip()
                    party = cells[1].text.strip()
                    votes = cells[2].text.strip()
                    writer.writerow([asmbcd, candidate, party, votes])

            print(f"选区 {asmbcd}: 数据抓取成功")

        except Exception as e:
            print(f"选区 {asmbcd}: 抓取失败 - {str(e)}")
            continue

注意事项

  • 请求头调整:若遇到403/401错误,直接复制浏览器中该接口请求的完整Headers(包括Cookie)替换代码中的HEADERS
  • 反爬应对:若网站限制请求频率,可延长time.sleep()的时间(如2-3秒)
  • 格式适配:若接口返回JSON而非XML,将XML解析部分替换为response.json(),直接提取数据节点
  • 数据验证:部分选区可能无2018年数据,代码会自动跳过并提示

内容的提问来源于stack exchange,提问作者Fuser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:54:57