求助:基于Network-Fetch/XHR抓取Asmbcd1-200的2018选举候选人投票数据
Karnataka 2018州议会选举数据抓取修正方案
现有代码的核心问题
- 错误使用GET请求调用ASMX WebService接口:这类接口通常要求POST请求,并携带指定参数
- 未传递关键参数:缺少选区编码
Asmbcd(1-200)和选举年份(2018)的必要参数 - 解析逻辑错误:ASMX接口返回的是包裹结构化数据的XML(而非直接HTML表格),直接用BeautifulSoup解析原始响应会失败
修正后的实现方案
关键调整点
- 改用POST请求,匹配接口要求的参数格式
- 循环遍历1-200的
Asmbcd值 - 先解析ASMX返回的XML,提取内部的HTML表格后再处理数据
- 加入错误处理与数据持久化(保存为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
相关产品推荐
相关产品推荐

