【问题标题】:Writing CSV file in Python from list with ascii使用 ascii 从列表中用 Python 编写 CSV 文件
【发布时间】:2021-06-13 20:50:03
【问题描述】:

我正在从 HTML 中提取表格。但我无法将其正确写入 csv 文件。在此之前我使用 argparser 但我必须更改,因为我想为很多文件创建一个循环。 我的代码是这样的:

import pathlib
import sys
import csv
import io
import bs4
import os

def detect_engine():
    try:
        import lxml
    except ImportError:
        engine = 'html.parser'
    else:
        engine = 'lxml'
    return engine


class Converter:

    def __init__(self, **kwargs):
        engine = kwargs.get('engine')
        if engine is None:
            self.engine = detect_engine()
        else:
            self.engine = engine
        self.params = kwargs

    def convert(self, html_doc):
        soup = bs4.BeautifulSoup(html_doc, self.engine)
        output = []
        for table_num, table in enumerate(soup.find_all('table')):
            csv_string = io.StringIO()
            # print(csv_string)
            csv_writer = csv.writer(csv_string)
            print(csv_writer)
            for tr in table.find_all('tr'):
                row = [''.join(cell.stripped_strings) for cell in tr.find_all(['td', 'th'])]
                csv_writer.writerow(row)
            table_attrs = dict(num=table_num)
            output.append((csv_string.getvalue(), table_attrs))
        return output

converter = Converter()
input_source = "html_file32.html"
path = pathlib.Path(input_source)
html_doc = path.read_text()
output = converter.convert(html_doc)
print(output)
with open('filename.csv', 'w') as myfile:
    wr = csv.writer(myfile, quoting=csv.QUOTE_ALL)
    wr.writerow(output)

我现在的输出是这样的:

"('รายการประมูลรถที่APPLEวันที่19กุมภาพันธ์2564,,,,,,,\r\nลำดับ,รายการรถยนต์,ทะเบียน,วันรับรถเข้าคลัง,สีรถ,ราคาขั้นต่ำ,ค่าโอน+VAT,,\r\nที่กำหนด(รวมVAT),,\r\n1,NISSAN JUKE 1.6 V,5กย3675,29/9/2016,WHITE SOLID,""320,000"",""2,000"",,\r\n2,TOYOTA REVO SMART CAB 2.4 J ROOF,1ฒศ4596,25/7/2016,SUPER\xa0 WHITE,""290,000"",""2,000"",,\r\n3,TOYOTA REVO SMART CAB 2.4 J ROOF(รถรุ่น ปี2016),1ฒฮ4547,14/3/2017,SUPER\xa0 WHITE,""290,000"",""2,000"",,\r\n4,TOYOTA REVO SMART CAB 2.4 J PLUS(รถรุ่น ปี2016),1ฒอ2820,3/2/2017,SILVER METALLIC,""310,000"",""2,000"",,\r\n5,TOYOTA REVO DOUBLE CAB 2.8 G 4WD DVD NAVIGATOR AUTO,6กท4269,19/8/2017,ATTITUDE BLACK MICA,""630,000"",""2,000"",,\r\n6,TOYOTA COMMUTER 3.0 D4D HIGH ROOF(รถรุ่น ปี2015),ฮษ1426,7/1/2016,WHITE,""400,000"",""3,000"",,\r\n7,\r\n', {'num': 0})"

我想要这样的东西:

รายการประมูลรถที่APPLEวันที่19กุมภาพันธ์2564,,,,,,,
ลำดับ,รายการรถยนต์,ทะเบียน,วันรับรถเข้าคลัง,สีรถ,ราคาขั้นต่ำ,ค่าโอน+VAT,,
ที่กำหนด(รวมVAT),,
1,NISSAN JUKE 1.6 V,5กย3675,29/9/2016,WHITE SOLID,"320,000","2,000",,
2,TOYOTA REVO SMART CAB 2.4 J ROOF,1ฒศ4596,25/7/2016,SUPER  WHITE,"290,000","2,000",,
3,TOYOTA REVO SMART CAB 2.4 J ROOF(รถรุ่น ปี2016),1ฒฮ4547,14/3/2017,SUPER  WHITE,"290,000","2,000",,
4,TOYOTA REVO SMART CAB 2.4 J PLUS(รถรุ่น ปี2016),1ฒอ2820,3/2/2017,SILVER METALLIC,"310,000","2,000",,
5,TOYOTA REVO DOUBLE CAB 2.8 G 4WD DVD NAVIGATOR AUTO,6กท4269,19/8/2017,ATTITUDE BLACK MICA,"630,000","2,000",,
6,TOYOTA COMMUTER 3.0 D4D HIGH ROOF(รถรุ่น ปี2015),ฮษ1426,7/1/2016,WHITE,"400,000","3,000",,
7,

【问题讨论】:

  • @buran 是的,实际上我从 filename.csv 复制输出
  • 您应该考虑使用utf-8 编码编写它。只要确保您用来查看/读取文件的内容也支持它。尝试添加:open('filename.csv', 'w', encoding='utf-8')
  • 一个问题是您已经使用 csv.writer 格式化了 output 中的数据,但是您再次使用 csv.writer 来写入文件。只需将output 直接写入文件,尽管最后额外的dict 很奇怪。你没有在你想要的输出中显示你想要的写法。
  • @MartinEvans 我试过了,但还是不行。还是谢谢
  • @MarkTolonen 是的,我不想要最后的额外字典。我发现的代码使用 argparse 并打印出所需的输出。

标签: python html python-3.x csv beautifulsoup


【解决方案1】:

尝试以下方法。它构建了一个行列表,每行都以table_num 为前缀,然后从convert() 返回。其次,它使用.writerows() 函数在一次调用中写入所有行。

注意,encoding='utf-8' 用于确保正确写入所有字符。这需要使用可以显示该编码的东西来查看(Excel 默认不显示)。添加newline='' 以确保在值也是多行的情况下正确处理换行符。

import pathlib
import sys
import csv
import io
import bs4
import os

def detect_engine():
    try:
        import lxml
    except ImportError:
        engine = 'html.parser'
    else:
        engine = 'lxml'
    return engine


class Converter:

    def __init__(self, **kwargs):
        engine = kwargs.get('engine')
        if engine is None:
            self.engine = detect_engine()
        else:
            self.engine = engine
        self.params = kwargs

    def convert(self, html_doc):
        soup = bs4.BeautifulSoup(html_doc, self.engine)
        output = []
        
        for table_num, table in enumerate(soup.find_all('table'), start=1):
            for tr in table.find_all('tr'):
                row = [''.join(cell.stripped_strings) for cell in tr.find_all(['td', 'th'])]
                output.append([table_num, *row])    
        
        return output

converter = Converter()
input_source = "html_file32.html"
path = pathlib.Path(input_source)
html_doc = path.read_text()
output = converter.convert(html_doc)
print(output)

with open('filename.csv', 'w', newline='', encoding='utf-8') as myfile:
    wr = csv.writer(myfile)
    wr.writerows(output)

【讨论】:

  • 非常感谢,虽然结果开头有一个额外的列,但它的作用就像一个魅力。
  • 我假设你的意思不是table_num。如果有您不想要的值,您可以在调用 output.append() 之前将其删除,例如del row[2]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-22
  • 1970-01-01
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
  • 2018-03-05
  • 2011-05-06
相关资源
最近更新 更多