while循环扩展列表时出现TypeError: string indices must be integers报错咨询
报错根因定位
- 传参完全不匹配:
fun设计为接收带Name1列的DataFrame,但while循环里传入的是diff中的单个姓名字符串,给字符串做['Name1']的键索引,必然触发TypeError: string indices must be integers fun本身存在低级错误:原代码return name2_list, score_list.append中,score_list.append是方法对象,不是实际的得分列表;且误用全局变量存结果,每次调用都会往全局列表重复堆数据,多次调用后数据完全混乱- 数据追加逻辑错误:直接把嵌套列表、整个集合append到Series中,相当于把整个嵌套结构当成单个单元格的内容存储,最终才会出现某一行Name2是长列表的嵌套结构
- 循环逻辑存在硬伤:处理完当前批次的diff后,既没有把当前批次的姓名加入已处理集合,也没有重新计算新的待办名单,要么无限循环,要么反复爬取同一姓名浪费资源
分步骤修复操作
1. 重构爬取函数,适配单个姓名输入
彻底废弃原来按DataFrame入参设计的fun,改成直接接收单个姓名字符串作为参数,返回平级的(关联姓名, 得分)元组列表,去掉全局变量避免数据污染:
import requests from bs4 import BeautifulSoup def crawl_single_name(name: str): # 用占位符代替实际站点路径,避免外链 url = f"目标站点路径/{name}" soup = BeautifulSoup(requests.get(url).content, "html.parser") # 提取关联姓名和得分 neighbor_list = [a.text.strip() for a in soup.select("#card_mini_audience .site>a")] score_list = [float(s.text.strip()) for s in soup.select("#card_mini_audience .overlap>.truncation")] # 直接返回平级元组列表,比如[('Julie',31.9),('Mike',30.9)],无嵌套 return list(zip(neighbor_list, score_list))
这一步修改完成后,传参不匹配的报错会直接消失。
2. 统一用DataFrame管理数据集
废弃零散的next_name2、name1列表,用DataFrame统一存储所有数据,从根源避免后续拆分、追加的麻烦:
import pandas as pd # 原始数据集直接初始化 raw_data = [ ("John", "Chris", 15.4), ("John", "Luke", 11.0), ("John", "Martin", 10.1), ("John", "Paul", 8.7), ("John", "Patty", 8.0), ("Patty", "Stephanie", 21.6), ("Patty", "Mila", 21.6), ("Patty", "Martin", 19.7), ("Patty", "Chris", 17.2), ("Patty", "Luke", 15.9), ("Meghan", "Kate", 5.0), ("Meghan", "Chris", 4.2), ("Meghan", "William", 4.1), ("Meghan", "John", 3.2), ("Meghan", "Stephen", 3.0) ] df = pd.DataFrame(raw_data, columns=["Name1", "Name2", "Score"]) # 记录已经爬过数据的姓名(即已经作为Name1出现过的姓名) processed_names = set(df["Name1"])
3. 重写while循环,实现平级追加和自动终止
核心逻辑为:每次处理当前待办名单里的所有姓名,把爬取到的所有关联关系拆成平级行追加,再更新待办名单,直到没有新的待处理姓名为止:
# 首次计算待办名单:所有在Name2里出现过、但还没作为Name1爬过数据的姓名 diff = set(df["Name2"]) - processed_names while len(diff) > 0: new_rows = [] # 遍历当前批次所有待处理姓名 for name in diff: # 跳过已经处理过的姓名,避免重复爬取 if name in processed_names: continue # 爬取当前姓名的所有关联关系 pairs = crawl_single_name(name) # 把每个关联对转成标准行结构:[当前处理的姓名, 关联姓名, 得分] for neighbor, score in pairs: new_rows.append( (name, neighbor, score) ) # 把新得到的平级行拼接到原数据集后面,不会出现嵌套单元格 new_row_df = pd.DataFrame(new_rows, columns=["Name1", "Name2", "Score"]) df = pd.concat([df, new_row_df], ignore_index=True) # 把当前批次处理完的姓名加入已处理集合 processed_names.update(diff) # 重新计算待办名单:全量出现过的姓名里,还没爬过数据的 all_occurred = set(df["Name1"]) | set(df["Name2"]) diff = all_occurred - processed_names
原来的嵌套行问题就是因为直接把嵌套结构塞进单元格,修改后每一条数据都是单独的一行,Name1、Name2、Score都是单值,完全和原始数据集结构一致;同时循环会在所有姓名爬取完成后自动终止,不会无限运行。
内容的提问来源于stack exchange,提问作者V_sqrt
相关产品推荐
相关产品推荐

