Python循环以国家为字典Key爬取Transfermarkt链接报KeyError问题
问题解决:按国家分栏存储爬取的球员链接
错误根因
- KeyError触发原因:你声明的
df是空字典,没有预先为国家名称创建对应的空列表,直接调用df[name].append()时系统找不到对应的键,自然抛出键不存在的错误。 - 所有国家重复存储相同链接的原因:外层循环的第m次迭代,本身就在爬取第m个国家对应的球员页面,当前页面所有有效球员链接都只属于
links_countries['countries'][m]这一个国家,你额外加了一层遍历所有国家名的循环,会导致每拿到一个链接就给所有国家的列表都添加一次,自然出现全字段重复的问题。
修复后的代码
import pandas as pd import time from bs4 import BeautifulSoup # 原始国家链接映射表 links_countries = pd.DataFrame({'links': {0: 'https://www.transfermarkt.co.uk/spieler-statistik/wertvollstespieler/marktwertetop/plus/0/galerie/0?ausrichtung=alle&spielerposition_id=alle&altersklasse=alle&jahrgang=0&land_id=1&kontinent_id=0&yt0=Show', 1: 'https://www.transfermarkt.co.uk/spieler-statistik/wertvollstespieler/marktwertetop/plus/0/galerie/0?ausrichtung=alle&spielerposition_id=alle&altersklasse=alle&jahrgang=0&land_id=2&kontinent_id=0&yt0=Show', 2: 'https://www.transfermarkt.co.uk/spieler-statistik/wertvollstespieler/marktwertetop/plus/0/galerie/0?ausrichtung=alle&spielerposition_id=alle&altersklasse=alle&jahrgang=0&land_id=3&kontinent_id=0&yt0=Show'}, 'countries': {0: 'Afghanistan', 1: 'Albania', 2: 'Algeria'}}) # 初始化结果字典,预先为每个国家创建空列表,避免KeyError final_data = {country: [] for country in links_countries['countries']} for m in range(len(links_countries)): # 拿到当前爬取的国家名 current_country = links_countries['countries'][m] driver.get(links_countries['links'][m]) time.sleep(3) soup = BeautifulSoup(driver.page_source, 'html5lib') pages = soup.select("#yw2 a") pag = [] for p in pages: pag.append(p.get_text(strip=True)) pag = [string for string in pag if string != ""] pag = int(pag[-1]) print('Page number', pag) href = [] for t in pages: href.append(t['href']) href = [string for string in href if string != ""] base_url = "https://www.transfermarkt.co.uk" + href[0].rstrip('123456789') for num in range(1, pag+1): url = base_url + str(num) print(url) driver.get(url) time.sleep(3) soup = BeautifulSoup(driver.page_source, 'html5lib') links = soup.find('table', {'class':'items'}).find_all("a") for li in links: link = li['href'].replace("#", '') # 过滤出球员链接,避免添加无关链接,可根据实际页面结构调整过滤规则 if '/spieler/' in link: # 仅给当前国家的列表添加链接+姓名,不要遍历所有国家 final_data[current_country].append({ 'name': li.get_text(strip=True), 'link': link }) # 可直接转成DataFrame输出,每列对应一个国家 result_df = pd.DataFrame(dict([ (k,pd.Series(v)) for k,v in final_data.items() ]))
核心修改说明
- 把最终存储结构改成预先初始化好所有国家key的字典,从根源避免KeyError
- 移除了冗余的全国家遍历逻辑,爬哪个国家的页面就把链接存到对应国家的列表下,不会出现重复存储的问题
- 增加了球员链接和姓名的匹配存储,同时过滤掉无关的a标签链接,避免无效数据入库
- 最后提供了转成DataFrame的逻辑,直接就能得到按国家分栏的结果
内容的提问来源于stack exchange,提问作者me.limes
相关产品推荐
相关产品推荐

