如何将main()函数的运行结果输出为CSV文件并解决西里尔字符乱码问题
问题修复方案
核心问题梳理
- 无法输出CSV:你的
main()函数最后仅执行了print(df)操作,没有使用return返回构造完成的DataFrame对象,调用main()时拿到的是空值,自然无法写入文件。 - 西里尔文本乱码:一是原代码直接将BeautifulSoup解析得到的Tag对象存入列表,没有提取标签内的纯文本内容;二是编码选择不合理,
cp1251是俄语西里尔编码,你爬取的是蒙古语西里尔站点,直接用utf-8-sig编码兼容性更强,既可以保证字符正确存储,用Excel打开也不会出现乱码。 - 额外隐藏问题:原代码在循环内部重复构造DataFrame,还存在
commission_year重复追加的逻辑,会导致列长度不匹配报错。
修正后的完整代码
import requests from bs4 import BeautifulSoup as BS from datetime import datetime import pandas as pd import re import csv today = datetime.today().strftime('%y%m%d ') def main(): page = 0 name = [] date = [] address = [] district = [] city = [] price = [] area_sqm = [] rooms = [] floor = [] commission_year = [] building_floors = [] garage = [] balcony = [] windows = [] window_type = [] floor_type = [] door_type = [] leasing = [] description = [] link = [] BASE = 'https://www.unegui.mn' URL = f'{BASE}/l-hdlh/l-hdlh-zarna/oron-suuts-zarna/5-r/?page=' COLUMNS=['Name','Date','Address','District','City','Price','Area_sqm','Rooms','Floor','Commission_year', 'Building_floors','Garage', 'Balcony','Windows','Window_type','Floor_type','door_type','Leasing','Description','Link'] with requests.Session() as session: while True: r = session.get(f'{URL}{page+1}') r.raise_for_status() m = re.search('.*page=(\d+)$', r.url) if m and int(m.group(1)) == page: break page += 1 print(f'Scrapping page {page}') soup = BS(r.text, 'lxml') for tag in soup.findAll('div', class_='list-announcement-block'): _name = tag.find('a', attrs={'itemprop': 'name'}) name.append(_name.get('content', 'N/A')) if (_link := _name.get('href', None)): link.append(f'{BASE}{_link}') _r = session.get(link[-1]) _r.raise_for_status() detail_soup = BS(_r.text, 'lxml') _spanlist = detail_soup.find_all('span', class_='value-chars') # 提取Tag对象的纯文本,加长度判断避免字段缺失报错 floor_type.append(_spanlist[0].get_text(strip=True) if len(_spanlist)>=1 else 'N/A') balcony.append(_spanlist[1].get_text(strip=True) if len(_spanlist)>=2 else 'N/A') garage.append(_spanlist[2].get_text(strip=True) if len(_spanlist)>=3 else 'N/A') window_type.append(_spanlist[3].get_text(strip=True) if len(_spanlist)>=4 else 'N/A') door_type.append(_spanlist[4].get_text(strip=True) if len(_spanlist)>=5 else 'N/A') windows.append(_spanlist[5].get_text(strip=True) if len(_spanlist)>=6 else 'N/A') _alist = detail_soup.find_all('a', class_='value-chars') commission_year.append(_alist[0].get_text(strip=True) if len(_alist)>=1 else 'N/A') building_floors.append(_alist[1].get_text(strip=True) if len(_alist)>=2 else 'N/A') area_sqm.append(_alist[2].get_text(strip=True) if len(_alist)>=3 else 'N/A') floor.append(_alist[3].get_text(strip=True) if len(_alist)>=4 else 'N/A') leasing.append(_alist[4].get_text(strip=True) if len(_alist)>=5 else 'N/A') district.append(_alist[5].get_text(strip=True) if len(_alist)>=6 else 'N/A') address.append(_alist[6].get_text(strip=True) if len(_alist)>=7 else 'N/A') rooms.append(tag.find('div', attrs={'announcement-block__breadcrumbs'}).get_text().split('»')[1].strip()) description.append(tag.find('div', class_='announcement-block__description').get_text().strip()) date.append(tag.find('div', class_='announcement-block__date').get_text().split(',')[0].strip()) city.append((tag.find('meta', attrs={'itemprop': 'areaServed'})).get('content')) if (_price := tag.find('meta', attrs={'itemprop': 'price'})) is None: _price = tag.find('div', class_='announcement-block__price _premium') price.append(_price.get_text().strip() if _price else 'N/A') # 循环结束后统一构造完整DataFrame并返回 df = pd.DataFrame(list(zip(name, date, address, district, city, price, area_sqm, rooms, floor, commission_year, building_floors, garage, balcony, windows, window_type, floor_type, door_type, leasing, description, link)), columns=COLUMNS) print(df) return df if __name__ == '__main__': df = main() # 使用utf-8-sig编码保证西里尔字符正常显示,Excel打开也不会乱码 df.to_csv(f'{today}HPD.csv', encoding='utf-8-sig', index=False)
内容的提问来源于stack exchange,提问作者WX1505
相关产品推荐
相关产品推荐

