我有很多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命令会更好。
答案 0 :(得分:0)
html可能非常混乱。因此,我建议使用比bash脚本更高级的内容。由于您已经用python-tag标记了问题(在以后的编辑中已正确替换为bash标记),所以让我们来看看python with BeautifulSoup。
编辑:在对此答案的评论中,OP的作者澄清了OP真正想要的:
如:
<td class="bzt">data12</td></code>
如:
<script src="hq.sohujs.cn/list=data18" type="text/javascript" charset="gbk"></script>
对当前工作目录中的所有html文件执行1.和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。
此答案的旧版本
以下脚本可完成您的描述:
收集当前目录中所有html文件的所有内容
使用制表符分隔符将其写入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样式表一起使用可能是最简单,最干净的方法。