【问题标题】:How to extract tables from many html files into one csv file?如何将多个 html 文件中的表格提取到一个 csv 文件中?
【发布时间】:2018-12-04 15:26:45
【问题描述】:

我有很多html文件,我想在每个html页面中提取表格和表格之外的其他信息,并将所有提取的信息合并到一个csv文件或制表符分隔文件中。虽然有"Best method of extracting text from multiple html files into one CSV file"的帖子,但我用我的html数据试了一下,速度很快但是结果只有一列数据,当然忽略了表外的信息。我已经预处理了html 文件到 output.txt ,其中包括我使用 bash 命令所需的表内部或外部的信息:

#!/bin/bash
for f in '*.html'; do   
    cat $f | sed -n '/tbody><tr/,/\/tbody>/p' > output.txt
done;

它做得很好,它给我们留下了关于桌子和我需要的其他信息的非常干净的信息。

output.txt的部分是这样的:

<tbody><tr><td><a href="fjzt-x.html?uid=NNNN">data11</a></td>
<td class="bzt">data12</td>
<td>data13</td>
    <td>data14</td>
<td>data15</td>
<td>data16</td>
<td>data17</td>
<td class="tdb"><span id="sNNNNN"></span></td>
<td class="tdb"><span id="zfNNNNN"></span></td>
<td class="bzt">--</td><td></td>
</tr>
<script src="https://hq.sohujs.cn/list=data18" type="text/javascript" charset="gbk"></script>
<script type="text/javascript">getprice1('NNNNN',NNNN,NNN);</script>
</code></pre>
<td><a href="fjzt-x.html?uid=NNNN">data21</a></td>
<td class="bzt">data22</td>
<td>data23</td>
    <td>data24</td>
<td>data25</td>
<td>data26</td>
<td>data27</td>
<td class="tdb"><span id="sNNNNN"></span></td>
<td class="tdb"><span id="zfNNNNN"></span></td>
<td class="bzt">--</td><td></td>
</tr>
<script src="https://hq.sohujs.cn/list=data28" type="text/javascript"  charset="gbk"></script>
<script type="text/javascript">getprice1('NNNNN',NNNN,NNN);</script>

...

我希望制表符分隔 Out Sample,如下所示:

data11  data12  data13  data14  data15  data16  data17  data18

data21  data22  data23  data24  data25  data26  data27  data28

谁能帮帮我? bash 或 python 命令会更好。

【问题讨论】:

    标签: linux bash html-table export-to-csv


    【解决方案1】:

    html 可能非常混乱。因此,我建议使用比 bash 脚本更高级的东西。由于您已经使用 python-tag 标记了问题(在以后的编辑中正确地替换为 bash 标记),让我们使用python with BeautifulSoup

    编辑:在对此答案的 cmets 中,OP 的作者澄清了 OP 真正想要的是什么:

    1. 在一个html表格中收集td标签的内容。

    如:

    <td class="bzt">data12</td></code>
    
    1. 另外从同一 html 文件中一个或多个脚本标记的 src 属性中的链接收集数据。

    如:

    <script src="hq.sohujs.cn/list=data18" type="text/javascript" charset="gbk"></script>
    
    1. 对当前工作目录中的所有 html 文件执行 1. 和 2.。

    2. 将此保存为 csv 表格,其中字段由 TAB ("\t") 分隔。

    python3 和 BeautifulSoup 的工作解决方案

    我从这个答案的早期版本扩展了脚本来做到这一点,并在 cmets 中添加了一些解释:

    """module import"""
    from bs4 import BeautifulSoup
    import glob
    
    """obtain list of all html files in cwd"""
    filenames = glob.glob("*.html")
    
    for filename in filenames:
        """parse each file with bs4"""
        soup = BeautifulSoup(open(filename), 'html.parser')
    
        """obtain data from td tags"""
        tdTextList = [td.text.strip().replace("\n","") for td in soup.find_all("td")]
    
        """clean data: remove empty strings"""
        tdTextList = [td for td in tdTextList if not td=='']
    
        """obtain data from script tag attributes"""
        scriptTags = soup.findAll("script")
        for elementTag in scriptTags:
            src_attribute = elementTag.attrs.get("src")
            if src_attribute is not None:
                src_elements = src_attribute.split("=")
                if len(src_elements) > 1:
                    tdTextList.append(src_elements[1])
    
        """write data to output002.csv"""
        with open("output002.csv", "a") as outputfile:
            for tdText in tdTextList:
                outputfile.write(tdText)
                outputfile.write("\t")
            outputfile.write("\n")
    

    如何运行

    从 html 文件所在目录中的终端执行:

    python3 <script_name.py>
    

    或者,您可以将工作目录移动到脚本开头的正确位置(html 文件所在的位置):

    import os
    os.chdir("</path/to/directory>")
    

    python2 和 BeautifulSoup 的工作解决方案

    由于OP的作者要求提供python2版本,我在这里提供一个。与上述 python3 版本的唯一区别是文件处理程序(python2 使用 file(),而不是 open())。

    """module import"""
    from bs4 import BeautifulSoup
    import glob
    
    """obtain list of all html files in cwd"""
    filenames = glob.glob("*.html")
    
    for filename in filenames:
        """parse each file with bs4"""
        soup = BeautifulSoup(file(filename), 'html.parser')
    
        """obtain data from td tags"""
        tdTextList = [td.text.strip().replace("\n","") for td in soup.find_all("td")]
    
        """clean data: remove empty strings"""
        tdTextList = [td for td in tdTextList if not td=='']
    
        """obtain data from script tag attributes"""
        scriptTags = soup.findAll("script")
        for elementTag in scriptTags:
            src_attribute = elementTag.attrs.get("src")
            if src_attribute is not None:
                src_elements = src_attribute.split("=")
                if len(src_elements) > 1:
                    tdTextList.append(src_elements[1])
    
        """write data to output002.csv"""
        with file("output002.csv", "a") as outputfile:
            for tdText in tdTextList:
                outputfile.write(tdText)
                outputfile.write("\t")
            outputfile.write("\n")
    

    运行python2版本类似于上面的python3。


    此答案的旧版本

    以下脚本执行您所描述的操作:

    1. 收集当前目录下所有html文件的全部内容

    2. 将它们写入带有制表符分隔符的 csv。

    这是一个示例脚本:

    from bs4 import BeautifulSoup
    import glob
    
    filenames = glob.glob("*.html")
    tdTextList = []
    for filename in filenames:
        soup = BeautifulSoup(open(filename), 'html.parser')
        tdTextList += [td.text for td in soup.find_all("td")]
    
    with open("output001.csv", "w") as outputfile:
        for tdText in tdTextList:
            outputfile.write(tdText)
            outputfile.write("\t")
    

    这就是你所描述的。这可能不是你想要的。

    请注意,这将生成一个包含单个非常长行的文件(您无需指定何时需要新行)。如果任何 td 标记的内容包含换行符,它可能会意外生成格式错误的文件。

    为了使输出文件看起来更好一些,让我们为每个读取的 html 文件写一个新行,并在将数据写入输出之前从数据中删除前导和尾随空格以及换行符。

    from bs4 import BeautifulSoup
    import glob
    
    filenames = glob.glob("*.html")
    
    for filename in filenames:
        soup = BeautifulSoup(open(filename), 'html.parser')
        tdTextList = [td.text.strip().replace("\n","") for td in soup.find_all("td")]
    
        with open("output002.csv", "a") as outputfile:
            for tdText in tdTextList:
                outputfile.write(tdText)
                outputfile.write("\t")
            outputfile.write("\n")
    

    注意:您可以使用以下命令从 bash shell 运行任一脚本:

    python3 <script_name.py>
    

    【讨论】:

    • 非常好的解决方案!我做了一些小的修改,它可以在python2.7中运行,但仍然缺少一些信息,如data18,data28,...这些信息不在表格中,当然倾斜是不合适的。使用 codecs.open("output002.csv", "a",encoding="utf-8") outputfile.write("\n") 导入编解码器
    • @james python2和python3有一些区别,主要是print语句(python2中不带括号)和文件IO(函数应该是file(),而不是python2中的open())。如果你愿意,我可以在答案中添加一个 python2 版本。
    • @james 您能否详细说明一下:仍有一些信息遗漏为 data18,data28,... 不在表格中如果我理解正确,您想要html中的字符串“data18”和“data28”也将被抓取。这些字符串出现在 html 中包含的脚本的 src url 中。与使用 td 标记从表中提取相比,这是一种特殊情况。可以这样做,但解决方案不会很通用。这是唯一的特例吗?另外,您能否在问题中包含 html 示例作为代码(而不是图片)?将更容易验证解决方案。
    • @james 您应该将 html 示例复制并发布为代码块,就像您发布代码一样:缩进 4 个字符,如 markdown help 中所述。请注意,在代码块中时,html 标签不会呈现,而是显示为 html。
    • ,非常感谢。代码:
       
      
      data11 data12 data13 data14 data15 data16 td> 
      data17    --
       
      
      
    【解决方案2】:

    您的示例数据看起来很干净。如果这表明了所有文件的结构,那么使用带有 XSLT 样式表的 xmlstarlet 可能是最简单、最干净的方法。

    【讨论】:

    • 这是一个非常强大的工具,可以在 UNIX shell 命令提示符下学习,并且可以与 shell 脚本结合,谢谢你,Kyle。
    • 我已经安装了那个 xmlstarlet,请给我更具体的脚本或步骤来完成这项工作,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 2013-07-13
    相关资源
    最近更新 更多