如何在Pandas DataFrame中仅当新艺人名称不在列中时追加行?
解决Pandas DataFrame仅追加新艺人行的问题
你现在遇到的核心问题是判断逻辑出错,导致无法正确过滤已存在的艺人,另外还有append()方法已被弃用的小问题,我来一步步帮你修正:
原代码的问题分析
- 判断逻辑颠倒:你写的
(all_data['artist'] != name).any()意思是「只要有一个艺人名字不等于当前name就追加」,这和你想要的「当前name不在列中才追加」完全相反;而且当DataFrame为空时,这个条件会返回False,导致第一行数据都加不进去。 append()已弃用:Pandas从2.0版本开始就标记append()为弃用状态,推荐用pd.concat()来实现数据合并,效率更高也更规范。- 全局变量可优化:全局变量
all_data会让代码可读性变差,后续维护也麻烦,我们可以调整写法避免它。
修正后的代码方案
方案1:快速修正核心逻辑(兼容原有结构)
import requests import bs4 import pandas as pd def get_webpage(i, url): URL = url + str(i) response = requests.get(URL) return bs4.BeautifulSoup(response.text, 'html.parser') COLUMNS = ['artist', 'netWorth'] all_data = pd.DataFrame(columns=COLUMNS) def scrape(soup): global all_data artists = soup.find_all('article', class_='thumb-wrap') # 先收集所有符合条件的新行,再批量合并(比逐行添加高效) new_entries = [] for ar in artists: name = ar.h3.a.text worth = ar.div.find('div', class_='bc-networth').text.strip() # 正确判断:DataFrame为空 或 当前name不在已有的artist列表中 if all_data.empty or name not in all_data['artist'].values: new_entries.append({'artist': str(name), 'netWorth': worth}) # 批量合并新数据 if new_entries: all_data = pd.concat([all_data, pd.DataFrame(new_entries)], ignore_index=True) # 爬取singer分类页面 i = 1 url = 'http://www.therichest.com/celebnetworth-category/celeb/singer/page/' while i <= 14: soup = get_webpage(i, url) scrape(soup) i += 1 # 爬取musician分类页面 i = 1 url = 'http://www.therichest.com/celebnetworth-category/celeb/musician/page/' while i <= 7: soup = get_webpage(i, url) scrape(soup) i += 1
方案2:避免全局变量的更规范写法
把已有的艺人列表作为参数传给scrape函数,让函数返回新数据,再在主逻辑里合并,代码耦合性更低:
import requests import bs4 import pandas as pd def get_webpage(i, url): URL = url + str(i) response = requests.get(URL) return bs4.BeautifulSoup(response.text, 'html.parser') def scrape(soup, existing_artists): artists = soup.find_all('article', class_='thumb-wrap') new_entries = [] for ar in artists: name = ar.h3.a.text worth = ar.div.find('div', class_='bc-networth').text.strip() # 用集合做判断,比Series的in操作快很多(数据量大时更明显) if name not in existing_artists: new_entries.append({'artist': str(name), 'netWorth': worth}) return new_entries COLUMNS = ['artist', 'netWorth'] all_data = pd.DataFrame(columns=COLUMNS) # 爬取singer分类 i = 1 url = 'http://www.therichest.com/celebnetworth-category/celeb/singer/page/' while i <= 14: soup = get_webpage(i, url) existing_artists = set(all_data['artist'].values) new_rows = scrape(soup, existing_artists) if new_rows: all_data = pd.concat([all_data, pd.DataFrame(new_rows)], ignore_index=True) i += 1 # 爬取musician分类 i = 1 url = 'http://www.therichest.com/celebnetworth-category/celeb/musician/page/' while i <= 7: soup = get_webpage(i, url) existing_artists = set(all_data['artist'].values) new_rows = scrape(soup, existing_artists) if new_rows: all_data = pd.concat([all_data, pd.DataFrame(new_rows)], ignore_index=True) i += 1
额外优化建议
- 反爬处理:可以给
requests.get()加上headers参数(比如设置User-Agent模拟浏览器),避免被网站拦截; - 数据类型转换:
netWorth现在是字符串,你可以后续处理成数值类型(比如去掉$和逗号后转成float),方便后续分析; - 异常捕获:爬取时可能遇到页面加载失败、标签找不到的情况,加上
try-except块能让代码更健壮。
内容的提问来源于stack exchange,提问作者user9737581
相关产品推荐
相关产品推荐

