Как извлечь таблицы из многих HTML-файлов в один CSV-файл? - PullRequest
0 голосов
/ 04 декабря 2018

У меня много html-файлов, и я хочу извлечь таблицу и другую информацию за пределы таблицы на каждой html-странице и объединить всю извлеченную информацию в один CSV-файл или файл с разделителями табуляции.Хотя есть сообщение «Лучший метод извлечения текста из нескольких html-файлов в один CSV-файл» , я пробую его, используя мои 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>
data21 data22 data23 data24 data25 data26 data27 -

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Ваш пример данных выглядит довольно чисто.Если это свидетельствует о том, как все файлы структурированы, использование xmlstarlet с таблицей стилей XSLT может быть самым простым и чистым способом.

0 голосов
/ 04 декабря 2018

HTML может быть очень грязным.Поэтому я бы предложил использовать что-то более высокое, чем скрипт bash.Так как вы уже пометили вопрос тегом python (справедливо замененным тегом bash в последующем редактировании), давайте перейдем к python с BeautifulSoup .

РЕДАКТИРОВАТЬ: В комментариях к этому ответу автор ОП уточнил, чего на самом деле хотел ОП:

  1. Собрать содержимое тегов td в HTML-таблице.

Как и в:

<td class="bzt">data12</td></code>
Дополнительно собирайте данные по ссылке в атрибуте src одного или нескольких тегов сценария в том же html-файле.

Как в:

<script src="hq.sohujs.cn/list=data18" type="text/javascript" charset="gbk"></script>

Выполните 1. и 2. для всех html-файлов в текущем рабочем каталоге.

Сохраните это как таблицу 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 можно запустить с помощью:

python3 <script_name.py>
...