如何用Selenium/BS提取网页表格并转为CSV或Pandas DataFrame?
解决USDA食品营养表格提取为DataFrame/CSV的问题
问题场景
我通过代码爬取USDA食品数据库,搜索关键词后选择目标食品(比如"Yogurt, plain, whole milk")进入详情页,尝试提取页面中的营养成分表格时,只能得到无结构的字符串,内容全部挤在一行,无法直接转换为CSV或Pandas DataFrame。
原搜索代码
from bs4 import BeautifulSoup import requests from selenium import webdriver import time from selenium.webdriver.common.keys import Keys from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys import pyautogui from selenium.webdriver.support.ui import WebDriverWait keyword='milk' browser = webdriver.Edge(r"C:\Users\solan\Documents\edgedriver_win32\msedgedriver.exe") browser.get('https://fdc.nal.usda.gov/fdc-app.html#/?query='+keyword+'') element1= browser.find_elements_by_xpath('//a[@class="result-description"]') for item in element1: print(item.text) Food= input("") time.sleep(10) browser.find_element_by_link_text(Food).click()
失败的表格提取代码
for table in browser.find_elements_by_xpath('/html/body/div/main/app-root/app-food-details/div/div/div[2]/div/div/div/app-food-nutrients/div/div[2]/table'): print(table.text)
解决方案
直接获取table.text会丢失表格的行列结构,必须解析HTML中的行(<tr>)和单元格(<td>/<th>)元素,按结构提取数据:
完整改进代码
from bs4 import BeautifulSoup import requests from selenium import webdriver import time from selenium.webdriver.common.keys import Keys from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys import pyautogui from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By import pandas as pd keyword='milk' browser = webdriver.Edge(r"C:\Users\solan\Documents\edgedriver_win32\msedgedriver.exe") browser.get('https://fdc.nal.usda.gov/fdc-app.html#/?query='+keyword+'') # 等待搜索结果加载完成 WebDriverWait(browser, 10).until( EC.presence_of_all_elements_located((By.XPATH, '//a[@class="result-description"]')) ) element1= browser.find_elements_by_xpath('//a[@class="result-description"]') for item in element1: print(item.text) Food= input("请输入要选择的食品名称:") # 等待目标元素可点击后再点击 WebDriverWait(browser, 10).until( EC.element_to_be_clickable((By.LINK_TEXT, Food)) ).click() # 等待营养表格加载完成 WebDriverWait(browser, 10).until( EC.presence_of_element_located((By.XPATH, '/html/body/div/main/app-root/app-food-details/div/div/div[2]/div/div/div/app-food-nutrients/div/div[2]/table')) ) # 解析表格数据 table = browser.find_element_by_xpath('/html/body/div/main/app-root/app-food-details/div/div/div[2]/div/div/div/app-food-nutrients/div/div[2]/table') rows = table.find_elements_by_tag_name('tr') # 提取表头和内容 data = [] for row in rows: cells = row.find_elements_by_tag_name('td') # 如果是表头行,用th元素 if not cells: cells = row.find_elements_by_tag_name('th') row_data = [cell.text.strip() for cell in cells] if row_data: # 跳过空行 data.append(row_data) # 转换为DataFrame df = pd.DataFrame(data[1:], columns=data[0]) print(df) # 导出为CSV文件 df.to_csv('food_nutrition.csv', index=False, encoding='utf-8-sig') # 关闭浏览器 browser.quit()
关键改进点
- 用
WebDriverWait替代time.sleep,确保元素加载完成后再操作,避免因页面加载慢导致的错误 - 逐行解析表格的
<tr>元素,再提取每行内的<td>/<th>文本,保留行列结构 - 直接将整理好的二维列表转换为Pandas DataFrame,方便后续处理和导出CSV
内容的提问来源于stack exchange,提问作者Rahul Solanki
相关产品推荐
相关产品推荐

