如何将网页爬取的数据合并为单个Pandas DataFrame?
问题根源分析
你遇到的核心问题是在for循环内部重复初始化列表了!每次遍历一个container时,你都重新定义了price_list = []、bedroom_list = [],这会把之前收集的数据全部清空,导致每个列表永远只存当前这一条数据。而且你把创建DataFrame和打印的代码也放在循环里,自然每次都会输出一个单行的小DataFrame。
修正方案:把列表初始化移到循环外
我们需要把三个列表的初始化放在for循环开始之前,这样每次循环只是往同一个列表里追加数据,最后再统一生成完整的DataFrame。
import pandas as pd from bs4 import BeautifulSoup # 先初始化三个空列表,放在循环外面! price_list = [] bedroom_list = [] bathroom_list = [] # 遍历所有containers for container in containers: try: price_container = container.find("a", {"class":"listing-price text-price"}) price_strip = price_container.text.strip() price_list.append(price_strip) # 直接追加,不再重新定义列表 except TypeError: # 如果当前container没有价格,也要保证三个列表长度一致,不然生成DataFrame会报错 price_list.append(None) bedroom_list.append(None) bathroom_list.append(None) continue try: bedroom_container = container.find("span", {"class":"icon num-beds"}) bedroom_strip = bedroom_container["title"] bedroom_list.append(bedroom_strip) except TypeError: bedroom_list.append(None) try: bathroom_container = container.find("span", {"class":"icon num-baths"}) bathroom_strip = bathroom_container["title"] bathroom_list.append(bathroom_strip) except TypeError: bathroom_list.append(None) # 循环结束后,统一创建字典和DataFrame data = {'price': price_list, 'bedrooms': bedroom_list, 'bathrooms': bathroom_list} df = pd.DataFrame(data) print(df)
另一种更简洁的写法:用列表收集字典
你之前尝试过列表推导式,但方向错了——应该遍历所有containers,把每个container对应的价格、卧室、浴室数据打包成一个字典,再把所有字典放进一个列表,最后转成DataFrame:
data_list = [] for container in containers: item = {} try: price_container = container.find("a", {"class":"listing-price text-price"}) item['price'] = price_container.text.strip() except TypeError: item['price'] = None try: bedroom_container = container.find("span", {"class":"icon num-beds"}) item['bedrooms'] = bedroom_container["title"] except TypeError: item['bedrooms'] = None try: bathroom_container = container.find("span", {"class":"icon num-baths"}) item['bathrooms'] = bathroom_container["title"] except TypeError: item['bathrooms'] = None data_list.append(item) df = pd.DataFrame(data_list) print(df)
这种写法的好处是,每个字典对应一行数据,逻辑更直观,也不用担心三个列表长度不一致的问题。
为什么你之前的推导式失效?
你写的data = [({'price':price, 'bedrooms':bedrooms, 'bathrooms':bathrooms}) for item in container]有两个问题:
- 遍历的是
container(单个容器)而不是containers(所有容器),所以会把单个容器的内容重复遍历多次 - 没有正确从每个
item(这里其实是container的子元素)中提取数据,导致重复添加同一个数据
内容的提问来源于stack exchange,提问作者goodaytar
相关产品推荐
相关产品推荐

