提取股票代码遇难题:pd.read_html无法保留空白字符
解决ETF代码与名称拆分问题:替代pd.read_html的方案
我之前也碰到过类似的情况——pd.read_html虽然能快速抓取表格,但它会自动合并单元格内的空白字符和换行,导致你没法拆分ETF代码和名称。这里给你一套用BeautifulSoup直接解析HTML的解决方案,亲测能完美保留原始文本结构:
步骤1:抓取分类列表
首先从主分类页获取所有ETF分类的URL后缀,这样就能拼接出每个分类的详情页链接:
import requests from bs4 import BeautifulSoup import pandas as pd # 主分类页面URL base_url = "https://etfdailynews.com/etfs/" response = requests.get(base_url) soup = BeautifulSoup(response.text, 'html.parser') # 提取分类链接后缀(比如"technology-equities-etfs") category_suffixes = [] # 用浏览器开发者工具查看页面结构后调整选择器,这里是示例 for link in soup.select('div.etf-categories a'): href = link.get('href') if href.startswith('/etfs/') and href != '/etfs/': suffix = href.split('/etfs/')[1].strip('/') category_suffixes.append(suffix)
步骤2:遍历分类页面,提取ETF代码和名称
每个分类页面里,Fund Symbol/Name列的单元格是代码在上、名称在下,用换行分隔。用BeautifulSoup就能直接拿到带换行的原始文本:
all_etfs = [] for suffix in category_suffixes: category_url = f"https://etfdailynews.com/etfs/{suffix}/" response = requests.get(category_url) soup = BeautifulSoup(response.text, 'html.parser') # 定位目标表格,同样需要根据实际页面结构调整选择器 table = soup.find('table', {'class': 'etf-table'}) if not table: continue # 跳过表头,遍历数据行 for row in table.find_all('tr')[1:]: cells = row.find_all('td') if len(cells) < 1: continue # 保留原始文本的换行和空格,这是拆分的关键 symbol_name_text = cells[0].get_text(strip=False) # 按换行拆分,过滤掉空行和多余空格 parts = [p.strip() for p in symbol_name_text.split('\n') if p.strip()] if len(parts) >= 2: symbol = parts[0] name = ' '.join(parts[1:]) # 名称可能有多行,合并成完整名称 all_etfs.append({ 'Symbol': symbol, 'Name': name, 'Category': suffix.replace('-etfs', '').replace('-', ' ').title() }) # 转成DataFrame方便后续处理 etf_df = pd.DataFrame(all_etfs) print(etf_df.head())
关键细节说明
get_text(strip=False)是核心:它不会自动去除换行符,让你能准确拆分代码和名称。- CSS选择器需灵活调整:你可以用浏览器的开发者工具查看页面结构,替换代码里的选择器(比如分类链接的容器、表格的class)。
- 异常处理:代码里加了简单判断,跳过没有表格或格式异常的页面,避免报错中断程序。
这样就能顺利提取到每只ETF的代码和对应名称啦!
内容的提问来源于stack exchange,提问作者NaT3z
相关产品推荐
相关产品推荐

