如何将许多HTML文件中的表格提取到一个csv文件中?

时间:2018-12-04 15:26:46

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

我有很多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命令会更好。

2 个答案:

答案 0 :(得分:0)

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

编辑:在对此答案的评论中,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的解决方案

我从此答案的早期版本扩展了脚本,以执行此操作,并在注释中添加了一些解释:

"""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>

答案 1 :(得分:0)

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