解决Pandas数据帧拼接InvalidIndexError问题、优化爬虫代码及实现多页数据合并保存至单个CSV
问题解决:Pandas拼接报错、爬虫代码优化与多页数据合并至CSV
一、解决pandas.errors.InvalidIndexError报错
你碰到的这个错误,根源是数据处理逻辑出了问题:你把三页的所有行都塞进同一个data列表,接着用data[0]、data[1]、data[2]分别作为三个DataFrame的列名——但data[1]其实是第一页的第一行数据,根本不是表头,而且三页的表头都重复混入了data列表,导致后续拼接时索引不唯一,触发了报错。
正确的做法是每一页单独提取表头和数据,确保每个DataFrame都使用正确的表头,同时避免表头行混入数据中。
二、优化爬虫代码(简洁流畅版)
你的原始代码手动处理3页,扩展性极差(如果有10页就得写10个URL、10个soup实例)。我们可以用循环自动遍历多页,复用会话连接和提取逻辑,让代码更简洁易维护:
优化后的完整代码
import requests from bs4 import BeautifulSoup import pandas as pd # 配置请求头和基础URL模板 headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'} base_url = "https://www.collincad.org/propertysearch?situs_street=Willowgate&situs_street_suffix=&isd%5B%5D=any&city%5B%5D=any&prop_type%5B%5D=R&prop_type%5B%5D=P&prop_type%5B%5D=MH&active%5B%5D=1&year=2021&sort=G&page_number={}" # 初始化会话和存储DataFrame的列表 session = requests.Session() dfs = [] # 遍历目标页数(这里是1-3页,可根据实际需求调整范围) for page_num in range(1, 4): # 构造当前页的完整URL current_url = base_url.format(page_num) # 发送请求并捕获请求错误 response = session.get(current_url, headers=headers) response.raise_for_status() # 解析页面 soup = BeautifulSoup(response.content, "lxml") # 提取表格所有行 table_rows = soup.select('#propertysearchresults tr') # 提取表头(表格第一行的<th>内容) table_headers = [col.get_text(' ', strip=True) for col in table_rows[0].select('th')] # 提取数据行(从第二行开始,过滤空行或长度不匹配的无效行) page_data = [] for row in table_rows[1:]: row_content = [col.get_text(' ', strip=True) for col in row.select('td')] if len(row_content) == len(table_headers): page_data.append(row_content) # 将当前页数据转为DataFrame并加入列表 page_df = pd.DataFrame(page_data, columns=table_headers) dfs.append(page_df) # 合并所有页的DataFrame,重置索引避免重复 final_df = pd.concat(dfs, axis=0, ignore_index=True) # 保存到CSV文件,不写入索引列 final_df.to_csv('Street.csv', encoding='utf-8', index=False)
关键优化点
- 循环自动生成URL:用URL模板+页码变量自动构造每一页的请求地址,后续爬取更多页只需修改循环范围。
- 复用会话连接:保持
Session实例,提升请求效率,避免重复建立连接。 - 独立处理每一页数据:每一页单独提取表头和数据,从根源避免了原始代码中表头与数据混杂的问题。
- 数据校验:过滤长度与表头不匹配的无效行,避免生成有问题的DataFrame。
- 重置索引:
concat时添加ignore_index=True,合并后生成连续的新索引,避免索引重复问题。
三、多页数据合并保存至单个CSV的核心逻辑
上面的代码已经完整实现了这个需求,核心步骤总结:
- 初始化空列表
dfs,用来存储每一页的DataFrame。 - 每爬取一页,就将该页数据转为DataFrame并添加到
dfs列表中。 - 用
pd.concat(dfs, axis=0, ignore_index=True)纵向合并所有DataFrame,axis=0表示按行拼接,ignore_index=True重置索引。 - 调用
to_csv()方法保存合并后的DataFrame,index=False避免将索引列写入CSV文件。
内容的提问来源于stack exchange,提问作者Achilles
相关产品推荐
相关产品推荐

