Python批量爬取多页div/tr/td表格数据导出CSV的脚本问题求助
问题1解答
原因
你没有对文件对象做主动关闭管理,Python向文件写入数据时会先放到内存缓冲区,只有缓冲区满、文件主动关闭、程序正常退出时才会把数据刷入磁盘。你直接用open(filename, 'w', newline='')创建文件对象但没有手动关闭,出现了缓冲区数据未及时落盘的情况,第二次运行时触发了上次运行残留的资源释放,才把数据写入第一次的文件。
修复方案
用with上下文管理器管理文件打开操作,运行结束后会自动关闭文件、刷入缓存,修改后的单页代码如下:
import requests import csv from bs4 import BeautifulSoup as bs url = requests.get("http://fcjyw.dlhitech.gov.cn/ysxkzList.xhtml?method=doQuery&selYsxk=xmmc&txtkey=&pageNo=1") soup = bs(url.content, 'html.parser') filename = "test.csv" # 用with管理文件 with open(filename, 'w', newline='') as f: csv_writer = csv.writer(f) divs = soup.find_all("div", class_ = "iiright") for div in divs: for tr in div.find_all("tr")[1:]: data = [] for td in tr.find_all("td"): data.append(td.text.strip()) if data: print("Inserting data: {}".format(','.join(data))) csv_writer.writerow(data)
问题2解答
错误点梳理
- 循环内只生成了url字符串,没有调用
requests.get发起请求,直接读取.content肯定报错 range(1,65)的取值范围是1到64,要爬65页需要改成range(1,66)if data的判断放在了td遍历的循环内部,会导致每采集一个单元格就写一次行,数据重复且不全,要移到td循环外部- 没有跳过表头行,和单页逻辑一致需要取
tr[1:] - writer变量是主程序里的局部变量,直接在函数内调用会有作用域风险,建议作为参数传入函数
修复后的多页代码
import requests import csv from bs4 import BeautifulSoup as bs base_url = "http://fcjyw.dlhitech.gov.cn/ysxkzList.xhtml?method=doQuery&selYsxk=xmmc&txtkey=&pageNo={}" def get_data(base_url, writer): # 改range到66,包含第65页 for page_no in range(1,66): # 发起请求,加超时防止卡死 resp = requests.get(base_url.format(page_no), timeout=10) soup = bs(resp.content, 'html.parser') for div in soup.find_all("div", class_ = "iiright"): # 跳过表头行 for tr in div.find_all("tr")[1:]: data = [] for td in tr.find_all("td"): data.append(td.text.strip()) # 移到td循环外判断 if data: print(f"Inserting page {page_no} data: {','.join(data)}") writer.writerow(data) if __name__ == '__main__': # 加utf-8-sig编码避免Excel打开CSV中文乱码,不需要可以删除 with open("test.csv","w",newline="", encoding='utf-8-sig') as f: writer = csv.writer(f) # 把writer作为参数传入 get_data(base_url, writer)
内容的提问来源于stack exchange,提问作者mike2851jgsa84
相关产品推荐
相关产品推荐

