Подтвердить что ты не робот

Скребок больших таблиц pdf, которые охватывают несколько страниц

Я пытаюсь скопировать таблицы PDF, которые охватывают несколько страниц. Я пробовал много вещей, но лучше всего pdftotext -layout советовать здесь. Проблема в том, что результирующий текстовый файл нелегко работать, поскольку расположение таблицы отличается от разных страниц, поэтому столбцы не выровнены. Также обратите внимание на отсутствующие значения в строках, начинающихся с "Solsonès":

                                                                        TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012

COMARCA          CODI i NOM EMA                    GEN    FEB    MAR         ABR       MAI      JUN      JUL          AGO        SET        OCT        N

Alt Camp         VY   Nulles                        7,5    5,5   10,9         12,3     16,7     21,6     22,3         24,4       20,1        15,9
Alt Camp         DQ   Vila-rodona                   7,9    5,6   11,0         12,0     16,6     21,6     22,0         24,3       19,9        15,8
Alt Empordà      U1   Cabanes                       8,2    6,5   11,7         12,6     17,5     22,0     23,1         24,4       20,4        16,6
Alt Empordà      W1   Castelló d'Empúries           8,1    6,4   11,6         12,9     17,0     21,1     22,0         23,4       20,1        16,4

[...]
                                                                                 TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012

COMARCA          CODI i NOM EMA                             GEN    FEB    MAR         ABR       MAI      JUN      JUL          AGO        SET        OCT

Baix Empordà     DF   la Bisbal d'Empordà                    6,6    5,3   10,9         12,6     17,2     21,9     22,9         24,6       20,3        16
Baix Empordà     UB   la Tallada d'Empordà                   6,1    5,2   10,7         12,3     16,6     21,3     22,2         23,8       19,7        15
Baix Empordà     UC   Monells                                6,1    4,6    9,9         11,4     16,5     21,7     23,0         24,5       19,6        15

[...]

                                                                        TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012

COMARCA         CODI i NOM EMA                      GEN    FEB    MAR         ABR       MAI      JUN      JUL           AGO        SET        OCT
[...]

Solsonès        CA   Clariana de Cardener            4,6    3,3   10,3         10,2     16,7     22,3      d.i.
Solsonès        Z8   el Port del Comte (2.316 m)    -0,9   -6,3   -0,2         -2,0      5,3     10,5     10,9          13,8        7,8         4,2
Solsonès        VO   Lladurs                         3,0    2,6    9,5          9,0     15,3     21,4     21,6          24,3       17,5        13,0
Solsonès        VP   Pinós                           3,0    1,6    8,9          9,2     15,4     21,1     21,3          23,8       17,6        13,3
Solsonès        XT   Solsona                                                                               d.i.         24,3       18,0        13,5
Tarragonès      VQ   Constantí                       7,9   6,0    11,2         13,1     17,1     21,9     22,6          24,6       20,6        16,6
Tarragonès      XE   Tarragona - Complex Educatiu   10,2   7,8    12,3         14,6     18,3     23,0     24,2          26,2       23,0 *      18,4
Tarragonès      DK   Torredembarra                   9,7   7,7    12,3         14,3     17,9     22,8     24,3          26,2       22,7        18,5
Terra Alta      WD   Batea                           6,3   5,0    11,2         12,1     18,3     23,0     23,3          25,5       20,2        15,9
Terra Alta      XP   Gandesa                         6,6   5,2    11,2         12,2     18,1     22,9     23,4          25,6       20,4        16,0

полный файл для загрузки - UTF8

Таким образом, этот вывод не очень просто разобрать. Какой другой подход доступен?

Кажется, что каждый инструмент, который я использую, способен извлекать информацию о макете ячеек таблицы, но не извлекает информацию о принадлежности к определенному столбцу. Это очень заметно, если ячейки пусты - пустые ячейки не выводятся, вы получаете только непустые "ячейки" с их компоновкой. В самом ли PDF файле содержится эта табличная информация? Если нет, нет смысла искать инструмент, который его извлечет.

Платные решения не могут быть и речи, поскольку в конечном итоге это может быть дешевле, чем инвестировать несколько рабочих дней моего времени...


Что я пробовал:

EDIT: облачный SDK, рекомендованный Яном. Я зарегистрировался, но я абсолютно не знаю, куда идти отсюда - как загружать страницы, узнавать их и т.д.:

enter image description here

4b9b3361

Ответ 1

Хорошо, я сделал это, и я думаю, что это поможет, хотя я не уверен, что вы хотите, чтобы ваш итоговый результат выглядел. Я рад работать над этим, поэтому дайте мне знать, есть ли части, в которых вам нужна помощь.


Я начал с загрузки PDF в текстовое приложение из CNET.

После установки я проверил следующие настройки:

PDF to text conversion

Важная часть здесь - это использование опции физического макета.

Это дало нам вывод, который выглядит так:

Taules de Dades de la Xarxa d’Estacions
    Meteorològiques Automàtiques
            2                                                                                                   Anuari de dades meteorològiques 2012 / Servei Meteorològic de Catalunya
            2                                                           TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012

COMARCA          CODI i NOM EMA                    GEN    FEB    MAR         ABR       MAI      JUN      JUL          AGO        SET        OCT        NOV         DES         ANY

Alt Camp         VY   Nulles                        7,5    5,5   10,9         12,3     16,7     21,6     22,3         24,4       20,1        15,9       11,0        8,5         14,8
Alt Camp         DQ   Vila-rodona                   7,9    5,6   11,0         12,0     16,6     21,6     22,0         24,3       19,9        15,8       11,0        8,6         14,7
Alt Empordà      U1   Cabanes                       8,2    6,5   11,7         12,6     17,5     22,0     23,1         24,4       20,4        16,6       11,8        8,3         15,3
Alt Empordà      W1   Castelló d'Empúries           8,1    6,4   11,6         12,9     17,0     21,1     22,0         23,4       20,1        16,4       12,1        8,5         15,0
Alt Empordà      VZ   Espolla                       9,0    6,7   12,4         12,7     17,8     22,0     23,3         24,8       20,9        16,7       12,0        8,9         15,6

[......]

             3                                                                                                           Anuari de dades meteorològiques 2012 / Servei Meteorològic de Catalunya
             2                                                                   TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012

COMARCA          CODI i NOM EMA                             GEN    FEB    MAR         ABR       MAI      JUN      JUL          AGO        SET        OCT        NOV         DES         ANY

Baix Empordà     DF   la Bisbal d'Empordà                    6,6    5,3   10,9         12,6     17,2     21,9     22,9         24,6       20,3        16,6       11,9        7,6         14,9
Baix Empordà     UB   la Tallada d'Empordà                   6,1    5,2   10,7         12,3     16,6     21,3     22,2         23,8       19,7        15,8       11,7        7,6         14,4
Baix Empordà     UC   Monells                                6,1    4,6    9,9         11,4     16,5     21,7     23,0         24,5       19,6        15,7       11,7        7,2         14,3
Baix Empordà     UD   Serra de Daró                          6,3    5,3   10,6         12,3     16,8     21,6     22,7         24,3       20,3        16,6       12,2        7,7         14,8

[......]

             4                                                                                                              Anuari de dades meteorològiques 2012 / Servei Meteorològic de Catalunya
             2                                                                      TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012

COMARCA           CODI i NOM EMA                               GEN    FEB    MAR         ABR       MAI      JUN      JUL          AGO        SET        OCT        NOV         DES         ANY

Maresme           UQ   Dosrius - PN Montnegre Corredor          7,2    4,6   10,8         10,7     15,8     20,4     20,8         23,4       18,6        15,1       10,7        7,8         13,9
Maresme           WT   Malgrat de Mar                           7,4    5,4   11,0         13,0     16,7     21,5     22,8         24,6       20,9        17,2       12,9        8,8         15,2
Maresme           DD   Vilassar de Mar                         10,1    7,5   12,6         13,9     17,9     22,4     23,7         25,7       22,1        18,4       13,8       10,8         16,6
Montsià           US   Alcanar                                 10,0    7,6   11,8         14,2     17,9     22,7     24,0         25,8       22,0        18,2       13,7       10,7         16,6
Montsià           UU   Amposta                                  9,6    7,5   12,1         14,3     18,3     22,8     23,5         25,3       21,6        18,0       13,1       10,8         16,4

[......]

Вы можете видеть, что строки столбцов намного лучше, но у нас также есть заголовки и номера страниц. Также столбцы COMARCA и i NOM EMA были переменной длины. Мы хотим нормализовать это для столбцов с фиксированной шириной.

Я написал программу Perl, чтобы ее нормализовать, а также сочетает таблицы с тем же заголовком и только печатает заголовки вверху. Он создает папку вывода со всеми файлами с названием в качестве имени файла.

Здесь код:

#!/bin/perl

use strict;
use warnings;
use open qw(:std :utf8);
use utf8;

my $comarca;
my $nom;
my $print_headers;
my $title = "";
my $fh;

while(<>) {

    if (    !/Xarxa d’Estacions/
        and !/Meteorològiques Automàtiques/
        and !/Servei/
        and !/^\s*\d+\s*$/
        and !/^\s*$/ ) {

        chomp($_);


        if ( /^\s*2/ ) { #title
            s/^\s*2\s*//;
            if ( $title ne $_ ) {
                $title = $_;
                $print_headers = 1;
            }

        } elsif ( /COMARCA/ ) { #column headers

            my ($first_col, $second_col, @the_rest) = split(/(CODI +i NOM EMA *)/, $_);


            $comarca = length $first_col;
            $nom = length $second_col;

            if ( $print_headers ) {
                my $str = sprintf "%-50s %-50s %s\n", $first_col, $second_col, join("", @the_rest);
                write_string($str);
                $print_headers = 0;
            }

        } else { #data

            my ($one, $two, $three) = unpack("A${comarca}A${nom}A*", $_);
            my $str = sprintf "%-50s %-50s $three\n", $one, $two;
            write_string($str);
        }

    }
}

sub write_string {

    my $string = shift;
    my $file_name = $title;
    $file_name =~ s/[\/\\]//g;

    open ($fh, '>>', ".\/output_folder\/${file_name}.txt") or die "Couldn't open: $!";
    print $fh $string;
    close ($fh);
}

На выходе все еще есть несколько недостатков (вы увидите их при запуске), но я хотел получить некоторую обратную связь о том, какой результат будет работать лучше всего для вас. Намного больше можно сделать, чтобы улучшить код! Дерево каталогов вывода выглядит следующим образом:

[email protected] ~/perl/pdftotext
$ find .
.
./convert.pl
./EMAtaules2012.txt
./output.txt
./output_folder
./output_folder/AMPLITUD TÈRMICA MITJANA MENSUAL ( ºC ) - 2012?.txt
./output_folder/AMPLITUD TÈRMICA MÀXIMA MENSUAL ( ºC ) - 2012?.txt
./output_folder/DIRECCIÓ DOMINANT DEL VENT - 2012?.txt
./output_folder/GRUIX MÀXIM MENSUAL DE NEU AL TERRA ( cm ) - 2012?.txt
./output_folder/HUMITAT RELATIVA MITJANA MENSUAL ( % ) - 2012?.txt
./output_folder/MITJANA MENSUAL DE LA HUMITAT RELATIVA MÀXIMA DIÀRIA ( % ) - 2012?.txt
./output_folder/MITJANA MENSUAL DE LA HUMITAT RELATIVA MÍNIMA DIÀRIA ( % ) - 2012?.txt
[......]

Если файл может выглядеть так:

COMARCA                                            CODI i NOM EMA                                     GEN    FEB    MAR         ABR       MAI      JUN      JUL          AGO        SET        OCT        NOV         DES         ANY
Alt Camp                                           VY   Nulles                                         7,5    5,5   10,9         12,3     16,7     21,6     22,3         24,4       20,1        15,9       11,0        8,5         14,8
Alt Camp                                           DQ   Vila-rodona                                    7,9    5,6   11,0         12,0     16,6     21,6     22,0         24,3       19,9        15,8       11,0        8,6         14,7
Alt Empordà                                        U1   Cabanes                                        8,2    6,5   11,7         12,6     17,5     22,0     23,1         24,4       20,4        16,6       11,8        8,3         15,3
Alt Empordà                                        W1   Castelló d'Empúries                            8,1    6,4   11,6         12,9     17,0     21,1     22,0         23,4       20,1        16,4       12,1        8,5         15,0
Alt Empordà                                        VZ   Espolla                                        9,0    6,7   12,4         12,7     17,8     22,0     23,3         24,8       20,9        16,7       12,0        8,9         15,6
Alt Empordà                                        D6   Portbou                                        9,6    5,5   12,7         12,5     17,4     21,5     22,9         24,4       19,8        17,0       12,3       10,1         15,5
[......]

Заголовки находятся только наверху, и все столбцы выстраиваются в линию. Это TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012.

Я думал о загрузке большего количества результатов на сайт для размещения файлов, но я не знаю, какой из них был бы хорош, предложения?

Надеюсь, это поможет вам Томасу!

EDIT: пример отсутствия записей AMPLITUD TÈRMICA MÀXIMA MENSUAL (ºC) - 2012:

Solsonès                                           VP   Pinós                          1              3,1   26   16,9   13   16,7   15   16,6   17   19,2   11   19,6   24   20,4    17      19,1   01   17,5   16   16,5   06   13,1   08   13,9   24   20,4    17/07
Solsonès                                           XT   Solsona                                                                                                              22,2    25      22,2   09   20,1   16   18,6   06   15,3   07   18,2   23   22,2    09/08
Tarragonès                                         VQ   Constantí                      1              6,4   19   21,9   23   19,7   11   12,9   07   17,4   23   17,2   21   15,1    18      14,2   18   18,0   15   15,1   02   14,9   07   16,0   10   21,9    23/02

Update

Обновлены скрипты для обработки входного файла:

#!/bin/perl

use strict;
use warnings;
use open qw(:std :utf8);
use utf8;
use charnames ':full';

my @column_lengths;
my $print_headers;
my $title = "";
my $fh;

while(<>) {

    if (    !/Xarxa d’Estacions/
        and !/Meteorològiques Automàtiques/
        and !/Servei/
        and !/^\s*\d+\s*$/
        and !/^\s*$/ ) {

        s/[\r\n]+//g;
        s/ +\d+$//;
        if ( /^\s*2/ ) { #title
            s/^\s*2\s*//;
            if ( $title ne $_ ) {
                $title = $_;
                $print_headers = 1;
            }

        } elsif ( /COMARCA/ ) { #column headers

            my $comarca = (split(/(COMARCA *)/, $_))[1];
            my $codi = (split(/(CODI *)/, $_))[1];
            my $inomema = (split(/(i NOM EMA *)  /, $_))[1];

            my $the_rest = (split(/(i NOM EMA *)  /, $_))[2];

            my @rest = split(/( \w+ *)/, $the_rest);

            undef @column_lengths;

            push @column_lengths, length $comarca;
            push @column_lengths, length $codi;
            push @column_lengths, length $inomema;

            for (@rest) {
                if ( $_ ) {
                    push @column_lengths, length $_;
                }
            }

            $column_lengths[-1] = "*";

            if ( $print_headers ) {
                $print_headers = 0;
                write_string(join(";", unpack( "A" . join("A", @column_lengths), $_)) . "\n");
            }

        } else { #data

            write_string(join(";", unpack( "A" . join("A", @column_lengths), $_)) . "\n");

        }

    }
}

sub write_string {

    my $string = shift;
    my $file_name = $title;
    $file_name =~ s/[º]//g;
    $file_name =~ s/[^\w ]//g;
    $file_name =~ s/ +/ /g;
    $file_name =~ s/È/E/g;
    $file_name =~ s/À/A/g;
    $file_name =~ s/Ó/O/g;
    $file_name =~ s/Í/I/g;
    $file_name =~ s/Ç/C/g;

    open ($fh, '>>', ".\/output_folder\/${file_name}.txt") or die "Couldn't open: $!";
    print $fh $string;
    close ($fh);
}

Этот объединяет линии с d.i. на следующей строке.

#!/bin/perl -i

use strict;
use warnings;

my $last = <>;

while(<>) {

    my @current_array = split(";", $_);

    if ( /^;+[ \t]+.d\.i\./ ) {

        my @last_array = split(";", $last);
        my @combined_array;

        #print "matches\n";

        for my $element (@current_array) {

            if ( $element =~ /d\.i\./ ) {
                push @combined_array, $element;
                shift @last_array;
            } else {
                push @combined_array, $last_array[0];
                shift @last_array;
            }

        }
        undef @current_array;
        @current_array = @combined_array;
    }
    $last = join ";", @current_array;
    print $last;

}

Выход в формате csv с разделителями с запятой.

Ответ 2

Вот решение R, но оно не лишено недостатков.

Часть 1: шаги настройки

# Read the lines of your file into R
x <- readLines("EMAtaules2012.txt")

# Make sure it shows up as UTF-8 to get proper accents and so on
Encoding(x) <- "UTF-8"

# Identify the lines where the data starts
Start <- grep("COMARCA", x)

# Grab the names of each table
ListNames <- gsub("\\s+", " ", x[Start-2])

# Figure out the number of rows of data per page
Runs <- rle(diff(cumsum(x != "")))
Nrows <- Runs$lengths[Runs$lengths > 4]+1

# Make our life easier by making this column name
#  a single string
x <- gsub("i NOM EMA", "i_NOM_EMA", x)

# Since these are fixed width files, we need to figure
#  out the widths of each column. This is the sum of
#  the number of characters in the header row plus
#  the number of spaces between each column name
Spaces <- gregexpr(x[Start], pattern="\\s+")
Spaces <- lapply(Spaces, function(x) c(attr(x, "match.length"), 0))
Chars <- lapply(strsplit(x[Start], "\\s+"), nchar)
Widths <- lapply(seq_along(Spaces), 
                 function(x) rowSums(cbind(Spaces[[x]], 
                                           Chars[[x]])))

Часть 2: Используя read.fwf, чтобы получить данные в

# Now, you can use `read.fwf` to read your data files in
temp <- lapply(seq_along(Start), function(fwf) {
  A <- read.fwf(textConnection(x), 
                widths = c(Widths[[fwf]]), 
                header = FALSE, 
                skip = Start[fwf]+1, 
                n = Nrows[fwf]-2, 
                blank.lines.skip = TRUE,
                strip.white = TRUE,
                stringsAsFactors = FALSE)
  # Add in the column names
  names(A) <- scan(what = "character", 
                   file = textConnection(x[Start[fwf]]), 
                   quiet = TRUE)
  A
})

# Assign the table names
names(temp) <- ListNames

# Some more cleanup. The original tables span multiple pages
#  in the PDF, but we can `rbind` them together in R
Tables <- unique(ListNames)
final <- lapply(seq_along(Tables), function(final) {
  A <- do.call(rbind, temp[names(temp) %in% Tables[final]])
  rownames(A) <- NULL
  A
})
# Add the names back in
names(final) <- Tables

Часть 3: Работало?

# View the first few rows and columns of the first three tables
lapply(final[1:3], function(y) head(y[1:5], 3))
# $` TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012`
#       COMARCA CODI           i_NOM_EMA GEN FEB
# 1    Alt Camp   DQ         Vila-rodona 7,9 5,6
# 2 Alt Empordà   U1             Cabanes 8,2 6,5
# 3 Alt Empordà   W1 Castelló d'Empúries 8,1 6,4
# 
# $` TEMPERATURA MÀXIMA MITJANA MENSUAL ( ºC ) - 2012`
#       COMARCA CODI           i_NOM_EMA  GEN  FEB
# 1    Alt Camp   DQ         Vila-rodona 13,1 11,7
# 2 Alt Empordà   U1             Cabanes 15,1 12,4
# 3 Alt Empordà   W1 Castelló d'Empúries 14,4 11,7
# 
# $` TEMPERATURA MÍNIMA MITJANA MENSUAL ( ºC ) - 2012`
#       COMARCA CODI           i_NOM_EMA GEN FEB
# 1    Alt Camp   DQ         Vila-rodona 3,8 0,5
# 2 Alt Empordà   U1             Cabanes 2,4 0,9
# 3 Alt Empordà   W1 Castelló d'Empúries 2,1 0,5

# Some tables, like those on page 76 (for the table "DIRECCIÓ DOMINANT DEL VENT"), had more columns than others. 
# Did our script take care of that?
names(final$` DIRECCIÓ DOMINANT DEL VENT`)
#  [1] "COMARCA"   "CODI"      "i_NOM_EMA" "vent"      "GEN"       "FEB"      
#  [7] "MAR"       "ABR"       "MAI"       "JUN"       "JUL"       "AGO"      
# [13] "SET"       "OCT"       "NOV"       "DES"       "ANY"    

Работает . Но ваш входной файл не идеален, и это означает, что все еще будет много очистки до. Например, некоторые столбцы в PDF, похоже, имеют несколько значений. Не знаете, как вы могли бы сделать какой-либо анализ на них.

Надеемся, что комментарии в приведенном выше коде помогут вам понять, как лучше соскабливать данные.


Обновление: извлечение только данных

Продолжая после "Части 1" выше, здесь решение, которое опирается на (вздох) Excel. Основная идея заключается в том, что Excel фактически выполняет довольно приличную работу по обнаружению разрыва столбца, если вы импортируете текст как Fixed Width.

Итак, мы используем R, чтобы разбить текст на отдельные страницы, один файл на страницу, только данные (не имена столбцов или имена строк, которые в основном одинаковы для всех наборов данных).

При этом здесь последний шаг R:

# Output just the data
temp <- lapply(seq_along(Widths), function(y) {
  DEL <- sum(Widths[[y]][1:3])-2
  A <- substring(x[(Start[y]+1):(sum(Start[y], Nrows[y]))], DEL)
  writeLines(A, paste("temp_", y, ".txt", collapse = ""))
  A
})

Откроем файл "temp_9.txt", который имеет недостающие столбцы:

enter image description here

^^ Убедитесь, что выбрана "Fixed Width" - она ​​должна быть по умолчанию, так как файл не имеет разделителей.

enter image description here

^ ^ Excel показывает вам предварительный просмотр того, где он будет создавать столбцы.

enter image description here

^^ Я выделил "строки проблем", чтобы вы могли увидеть, как это работает.

Ответ 3

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

Я написал большую часть pdftables, извинения за непрозрачность! Он работает нормально для некоторых страниц документа, который вы показываете, например, страница 2 дает мне вывод в нижней части этого ответа. Например, для других страниц он падает, например, на стр. 33. Проблема здесь в том, что есть два числа под одним заголовком столбца, и они застревают вместе pdftables. Столбцы "COMARCA, CODI i, NOM EMA" не разделяются в обоих случаях. Вы можете отправлять вопросы для pdftables на GitHub, я не работаю над этим активно в данный момент. Он доступен для установки pip.

Если вы хотите пойти по коммерческому маршруту, то Abbyy FineReader очень хорош, они производят облачный SDK, который даст вам 30 или около того страниц бесплатно. У них есть пример кода на нескольких языках, но их поддержка невелика.

     14 columns, 39 rows
                                      0    1    2    3    4    5    6    7    8    9   10   11   12   13
    -----------------------------------------------------------------------------------------------------
  0 |             COMARCACODI i NOM EMA| GEN| FEB| MAR| ABR| MAI| JUN| JUL| AGO| SET| OCT| NOV| DES| ANY|
  1 |                  VYNullesAlt Camp| 7,5| 5,5|10,9|12,3|16,7|21,6|22,3|24,4|20,1|15,9|11,0| 8,5|14,8|
  2 |             DQVila-rodonaAlt Camp| 7,9| 5,6|11,0|12,0|16,6|21,6|22,0|24,3|19,9|15,8|11,0| 8,6|14,7|
  3 |              Alt EmpordàU1Cabanes| 8,2| 6,5|11,7|12,6|17,5|22,0|23,1|24,4|20,4|16,6|11,8| 8,3|15,3|
  4 |  Alt EmpordàW1Castelló d'Empúries| 8,1| 6,4|11,6|12,9|17,0|21,1|22,0|23,4|20,1|16,4|12,1| 8,5|15,0|
  5 |              Alt EmpordàVZEspolla| 9,0| 6,7|12,4|12,7|17,8|22,0|23,3|24,8|20,9|16,7|12,0| 8,9|15,6|
  6 |              D6PortbouAlt Empordà| 9,6| 5,5|12,7|12,5|17,4|21,5|22,9|24,4|19,8|17,0|12,3|10,1|15,5|
  7 |                D4RosesAlt Empordà| 9,3| 7,2|13,0|13,6|18,2|22,6|23,9|25,7|21,3|17,5|13,2| 9,9|16,3|
  8 |   Alt EmpordàU2Sant Pere Pescador| 7,8| 6,3|11,5|12,9|16,8|21,2|22,2|23,6|20,2|16,5|12,3| 8,5|15,0|
  9 |  Alt EmpordàW2Torroella de Fluvià| 7,4| 6,0|11,2|12,6|16,4|21,2|22,3|23,7|19,9|16,1|11,7| 8,0|14,7|
 10 |             Alt EmpordàW3Ventalló| 7,3| 6,2|11,4|12,8|16,9|21,8|22,8|24,3|20,4|16,5|12,0| 8,1|15,1|
 11 |            Alt PenedèsWPCanaletes| 7,0| 5,2|11,3|11,9|16,7|21,5|22,0|24,2|19,7|15,6|10,7| 8,1|14,5|
 12 |            Alt PenedèsDIFont-rubí| 8,1| 6,2|12,0|11,9|16,9|21,8|22,0|24,4|20,0|15,9|11,4| 8,9|15,0|
 13 |           Alt PenedèsW4la Granada| 7,0| 5,5|11,2|12,6|17,2|21,9|22,4|24,3|20,0|16,0|11,1| 8,3|14,8|
 14 |   Alt PenedèsU3Sant Martí Sarroca| 6,4| 5,1|10,9|12,4|17,0|21,8|22,3|24,3|19,9|15,7|10,8| 8,0|14,6|
 15 | Alt PenedèsWYSant Sadurní d'Anoia| 6,4| 5,1|11,0|12,8|17,6|22,6|23,2|25,0|20,5|16,2|10,9| 7,8|15,0|
 16 |       CDla Seu d'UrgellAlt Urgell| 3,6| 2,5| 8,5| 8,4|14,6|20,3|21,0|23,4|16,9|12,2| 7,0| 3,2|11,8|
 17 |                W5OlianaAlt Urgell| 2,0| 2,7| 9,8|10,2|16,8|23,0|22,9|25,6|19,1|13,9| 8,6| 3,1|13,2|
 18 |               Alt UrgellCJOrganyà| 2,6| 3,5| 9,8| 9,9|16,1|22,0|22,6|25,3|18,8|13,5| 8,2| 2,9|13,0|
 19 |     Alta RibagorçaZ2Boí (2.535 m)|-2,4|-7,5|-1,3|-3,4| 3,8| 8,6| 9,4|12,0| 6,3| 2,7|-1,1|-3,2| 2,0|
 20 |  Alta RibagorçaCTel Pont de Suert| 0,5| 1,6| 6,9| 7,9|14,1|18,0|19,1|20,4|15,7|10,7| 6,1| 1,3|10,2|
 21 |   CEels Hostalets de PierolaAnoia| 7,3| 5,5|11,7|12,1|17,4|22,4|22,9|25,2|20,3|16,2|11,1| 8,3|15,1|
 22 |                 XBla LlacunaAnoia| 5,4| 3,3| 9,3|10,3|15,6|20,8|20,9|23,3|18,0|14,1| 9,1| 6,9|13,1|
 23 |               AnoiaXAla Panadella| 3,6| 1,7| 9,2| 8,7|14,9|20,5|20,4|23,2|17,2|13,3| 7,9| 5,1|12,2|
 24 |                      H1Ã’denaAnoia| 5,1| 3,3| 9,4|11,5|16,3|21,7|22,5|24,6|19,4|15,2| 9,3| 6,0|13,7|
 25 |                      WWArtésBages| 3,5| 2,8| 9,2|11,2|16,6|22,4|23,2|25,1|19,3|15,0| 9,1| 4,3|13,5|
 26 |        U4Castellnou de BagesBages| 4,8| 3,8|10,5|10,9|16,3|22,0|22,5|25,0|19,3|15,0| 9,6| 5,9|13,9|
 27 |        R1el Pont de VilomaraBages| 3,8| 3,1| 9,9|12,3|17,4|22,9|23,5|25,4|20,0|15,7| 9,7| 5,0|14,1|
 28 |    BagesWNMontserrat - Sant Dimes| 6,2| 3,3| 9,7| 8,6|14,8|19,5|19,5|22,4|16,9|13,5| 9,0| 7,1|12,6|
 29 | CLSant Salvador de GuardiolaBages| 3,3| 2,8| 9,1|11,5|16,4|22,0|22,4|24,6|19,2|14,9| 9,1| 4,8|13,4|
 30 |   U5Prades - los HortalsBaix Camp| 2,8| 0,0| 6,4| 7,4|13,0|18,4|18,0|21,3|15,0|11,3| 6,5| 4,1|10,4|
 31 |                W6RiudomsBaix Camp| 9,7| 7,1|12,0|13,4|17,6|22,4|23,1|25,2|21,2|17,1|12,3|10,1|16,0|
 32 |     U6Vinyols i els ArcsBaix Camp|10,2| 7,6|12,0|13,8|17,6|22,5|24,0|25,9|22,3|18,2|13,2|11,1|16,6|
 33 |                Baix EbreU7Aldover|10,0| 8,5|13,2|14,8|19,7|24,6|25,2|27,1|22,7|18,3|12,9|11,1|17,4|
 34 |             DBel PerellóBaix Ebre| 8,7| 7,0|12,0|13,3|17,9|22,6|23,3|25,3|21,4|17,2|11,9|10,3|15,9|
 35 |                U9l'AldeaBaix Ebre| 9,9| 8,1|12,5|14,3|18,5|23,3|24,1|26,0|22,1|17,9|13,1|10,7|16,8|
 36 |       UAl'Ametlla de MarBaix Ebre| 9,6| 7,8|12,3|13,8|18,0|22,9|23,9|25,8|22,0|17,6|12,5|10,6|16,4|
 37 |          Baix EbreX5PN dels Ports| 3,4|-0,2| 6,5| 6,8|13,4|18,7|17,8|21,2|15,2|11,3| 6,1| 4,9|10,5|
 38 |       Baix EmpordàDOCastell d'Aro| 6,7| 5,1|10,6|12,0|16,2|20,9|21,8|23,8|20,1|16,3|12,2| 8,1|14,5|
    -----------------------------------------------------------------------------------------------------  

Проблемы с юникодом сводятся к моей среде dev (Spyder).

Ответ 4

Если вы опасаетесь погружения слишком глубоко в Python или другие решения на основе кода, совершенно другой подход для быстрого и грязного решения для небольшого числа PDF файлов заключается в том, чтобы передать задачу на MechanicalTurk.

Наличие нескольких пользователей в одном столбце позволяет дважды проверять представленные ответы, а также публиковать полученную таблицу .csv и оплачивать большую сумму (скажем, 5 долларов США) за каждую ошибку, которую может найти рабочий. Часто заканчивается тем, что он дешевле, чем ваше программирование или время программирования.

Ответ 5

Хотя при использовании pdftotext макет отличается от разных страниц, обратите внимание, что заголовки столбцов на отдельных страницах (COMARCA, CODI и т.д.), похоже, совпадают с данными на этой странице.

Кроме того, в вашем формате pdf есть много разных типов данных: направление ветра, сила ветра, влажность, осадки и т.д. Таким образом, макет не только отличается от разных страниц для одних и тех же данных, но макет отличается тем, что есть и другие наборы данных.

И только для полноты - отсутствующие данные для "Solsonès" (как один пример) существуют в оригинале PDF. Кажется, что pdftotext выполнил разумную работу - недостающие данные - это пробелы, как в исходном PDF файле.

В результате может иметь смысл оставаться с pdftotext и обрабатывать страницы (которые разделены фидами форм) в виде столбчатых данных и анализировать, используя struct, как описано здесь:

Как эффективно анализировать файлы фиксированной ширины?

Один из способов сделать эту работу - обнаружить фид формы, найти следующую строку, начинающуюся с "COMARCA", и использовать интервал в этой строке для настройки столбцов для struct.

Ответ 6

Усилия по созданию индекса для этого (по-видимому, изменение форматов относится к различным подзаголовкам. Все это похоже на Каталонию:

heads <- grep("                                                                .+2012", txt)
notheads <- grep("                                                                .+Anuari de", txt)
 headtxt <-  unique(trim(txt[1:length(txt) %in% heads & !1:length(txt) %in% notheads]))

 [1] "TEMPERATURA MITJANA MENSUAL ( ºC ) - 2012"                            
 [2] "TEMPERATURA MÀXIMA MITJANA MENSUAL ( ºC ) - 2012"                     
 [3] "TEMPERATURA MÍNIMA MITJANA MENSUAL ( ºC ) - 2012"                     
 [4] "TEMPERATURA MÀXIMA ABSOLUTA MENSUAL ( ºC ) - 2012"                    
 [5] "TEMPERATURA MÍNIMA ABSOLUTA MENSUAL ( ºC ) - 2012"                    
 [6] "AMPLITUD TÈRMICA MITJANA MENSUAL ( ºC ) - 2012"                       
 [7] "AMPLITUD TÈRMICA MÀXIMA MENSUAL ( ºC ) - 2012"                        
 [8] "NOMBRE DE DIES DE GLAÇADA ( TN ≤ 0 ºC ) - 2012"                       
 [9] "PRECIPITACIÓ MENSUAL ( mm ) - 2012"                                   
[10] "PRECIPITACIÓ MENSUAL MÀXIMA EN 24 HORES ( mm ) - 2012"                
[11] "PRECIPITACIÓ MENSUAL MÀXIMA EN 1 HORA ( mm ) - 2012"                  
[12] "PRECIPITACIÓ MENSUAL MÀXIMA EN 30 MINUTS ( mm ) - 2012"               
[13] "PRECIPITACIÓ MENSUAL MÀXIMA EN UN 1 MINUT ( mm ) - 2012"              
[14] "NOMBRE DE DIES DE PRECIPITACIÓ (PPT ≥ 0,1 mm) - 2012"                 
[15] "NOMBRE DE DIES DE PRECIPITACIÓ (PPT > 0,2 mm) - 2012"                 
[16] "VELOCITAT MITJANA DEL VENT MENSUAL ( m/s ) - 2012"                    
[17] "DIRECCIÓ DOMINANT DEL VENT - 2012"                                    
[18] "MITJANA MENSUAL DE LA RATXA MÀXIMA DIÀRIA DEL VENT ( m/s ) - 2012"    
[19] "RATXA MÀXIMA ABSOLUTA DEL VENT MENSUAL ( m/s ) - 2012"                
[20] "HUMITAT RELATIVA MITJANA MENSUAL ( % ) - 2012"                        
[21] "MITJANA MENSUAL DE LA HUMITAT RELATIVA MÀXIMA DIÀRIA ( % ) - 2012"    
[22] "MITJANA MENSUAL DE LA HUMITAT RELATIVA MÍNIMA DIÀRIA ( % ) - 2012"    
[23] "MITJANA MENSUAL DE LA IRRADIACIÓ SOLAR GLOBAL DIÀRIA ( MJ/m2 ) - 2012"
[24] "PRESSIÓ ATMOSFÈRICA MITJANA MENSUAL, A NIVELL DE L'EMA ( hPa ) - 2012"
[25] "PRESSIÓ ATMOSFÈRICA MÀXIMA ABSOLUTA MENSUAL ( hPa ) - 2012"           
[26] "PRESSIÓ ATMOSFÈRICA MÍNIMA ABSOLUTA MENSUAL ( hPa ) - 2012"           
[27] "GRUIX MÀXIM MENSUAL DE NEU AL TERRA ( cm ) - 2012"  

Параны и тире препятствуют grepping. Поэтому попытка попасть в форму, где эти значения могут использоваться для определения местоположений заголовка страницы с помощью grep(val, txt), удалась, удалив совпадение "\\(.+$" с единственным исключением (которое я решил исправить вручную):

 headtxt[14:15]
#[14] "NOMBRE DE DIES DE PRECIPITACIÓ (PPT ≥ 0,1 mm) - 2012"                 
#[15] "NOMBRE DE DIES DE PRECIPITACIÓ (PPT > 0,2 mm) - 2012"  

headtxt <- gsub("\\(.+$", "", headtxt)

pagedivs <- lapply(headtxt, grep, txt)
# Seemed reasonable that the first 5 (of 10) should be the first section
pagedivs[[14]] <- pagedivs[[14]][1:5]
pagedivs[[15]] <- pagedivs[[15]][6:10]

Итак, ища маркер для завершения страниц, похоже, что 4 пустые строки надежны

> length(notheads)
[1] 113
> rl.lens <- rle( nchar(txt) )
> table(rl.lens$lengths[rl.lens$values==0])
#  1   4 
#226 113 

Удалено все "Ã", поскольку они создают столбцы с нефиксированной шириной:

txt <- gsub("Ã", "", txt)
write(txt, "txt_noAs.txt)

Интересно, что в моем текстовом редакторе теперь отображается "à", где раньше появлялась "Ã". На этом этапе можно перебирать страницы в пределах типа страницы, начиная с pagedivs + 4, до местоположения 4 пустых строк и использовать read.fwf из пакета utils. Остается поддержать это определение макета, о котором вы говорите, у вас уже есть дескриптор, но который также можно сделать с помощью pkg: gsubfn strapply или регулярного выражения.

Ищете подход к разработке решения регулярных выражений:

> numfields <- gregexpr("[-[:digit:].]+ ", txt)
> table( sapply( numfields,  length))

   1    2    3    5    6    7    8   11   12   13   14   15 
1201  193    8    1   13   15    2    4 1162  869  308   32 
  16   17   19   20   21   23   24   25   26   27   28   30 
   1    3    1    1    1    7   10  688  481  168   13    1 

Таким образом, страницы попадают в два класса: те, где число числовых столбцов равно 12-14, и числа, где они имеют номер 23-28. Я ожидал, что это будет немного иначе, но я думаю, что "ЛЮБЫЕ" столбцы отбросили мои ожидания.

Ответ 7

Очень ясно, что исходная таблица Excel состояла из разных листов, в которых использовались разные ширины столбцов.

Таким образом, в таблицах PDF также используются разные ширины столбцов. Если вы посмотрите на PDF, вы увидите следующие группы диапазонов страниц, которые имеют одинаковые ширины столбцов. Каждая группа также описывает разные вещи, как видно из заголовков изменений для каждой стартовой страницы группы (я могу идентифицировать эти различия, даже не имея возможности понять испанский язык):

  • страницы 2-6 (5 страниц)
  • страницы 7-11 (5 страниц)
  • страницы 12-16 (5 страниц)
  • страницы 17-21 (5 страниц)
  • страницы 22-26 (5 страниц)
  • страницы 27-31 (5 страниц)
  • страницы 32-36 (5 страниц)
  • страницы 37-41 (5 страниц)
  • страницы 42-46 (5 страниц)
  • страницы 47-51 (5 страниц)
  • страницы 52-56 (5 страниц)
  • страницы 57 + 58 (2 страницы)
  • страницы 59-62 (4 страницы)
  • страницы 63-67 (5 страниц)
  • страницы 68-72 (5 страниц)
  • страницы 73-76 (4 страницы)
  • страницы 77-80 (4 страницы)
  • страницы 81-84 (4 страницы)
  • страницы 85-88 (5 страниц)
  • страницы 89-93 (5 страниц)
  • страницы 84-98 (5 страниц)
  • страницы 99-103 (5 страниц)
  • страницы 104-107 (4 страницы)
  • страницы 108 + 109 (2 страницы)
  • страницы 110 + 111 (2 страницы)
  • страницы 112 + 113 (2 страницы)
  • наконец, стр. 114 (только 1 страница)

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

Чтобы показать вам пример (созданный с помощью Poppler версии pdftotext):

pdftotext \ -layout \ -enc UTF-8 \ -f 22 -l 26 \ -nopgbrk \ -x 20 -y 82 \ -W 810 -H 450 \ EMAtaules2012.pdf \ -

  • -f 22 -l 26:
    Это говорит, что инструмент извлекает страницу 22 как первую в диапазоне, а страницу 26 - как последнюю.
  • -nopgbrk:
    Сообщает, что инструмент не вставляет разрывы страниц.
  • -x 20 -y 82:
    Устанавливает верхний левый угол (в пикселях) области, из которой извлекаются данные таблицы. Обратите внимание: здесь я использовал такие значения, которые также исключают заголовки столбцов, а не только заголовки страниц и имена таблиц.
  • -W 810 -H 450. Устанавливает ширину и высоту (в пикселях) области, используемой для извлечения данных таблицы.

Примечание. Если вы используете версию XPDF pdftotext (как доступно в www.foolabs.com/xpdf/download.html) параметры командной строки для -x, -y, -W и -H не поддерживаются. Но если вы используете -table вместо -layout с XPDF-pdftotext, тогда результат должен быть схожим (вам все равно придется вручную удалять заголовки страниц и столбцов).

Выше команда дает вам этот вывод (я показываю только вывод для первых двух страниц с переходом ширины на ровной границе страницы, 2 строки после записей Baix Ebre):

Alt Camp         VY   Nulles                        -1,4   19    -4,9   12     1,1   07     4,0   07    4,8   01   11,2   13   12,0   02   12,7   31    8,3   27     0,7   29     0,1   30    -1,7   01    -4,9   12/02
Alt Camp         DQ   Vila-rodona                   -0,5   30    -4,5   03     1,3   07     3,4   17    5,5   02   13,0   14   12,8   02   14,6   31    8,9   27     2,6   28     0,2   30     0,6   12    -4,5   03/02
Alt Empordà      U1   Cabanes                       -3,0   15    -6,0   09    -0,3   02     2,9   25    3,6   01   12,2   11   10,5   24   12,6   27    6,6   27     2,8   30     2,0   30    -4,3   12    -6,0   09/02
Alt Empordà      W1   Castelló d'Empúries           -2,7   15    -6,2   09     0,3   02     3,2   07    6,0   01   12,1   16   11,1   24   13,3   27    7,5   27     0,7   30     2,2   23    -3,7   12    -6,2   09/02
Alt Empordà      VZ   Espolla                       -1,8   15    -6,8   09     1,5   19     2,9   07    5,7   01   12,2   12   10,3   24   13,7   07    7,6   20     2,5   30     2,5   07    -4,8   12    -6,8   09/02
Alt Empordà      D6   Portbou                        1,7   29    -4,5   04     4,8   06     3,3   16    9,4   01   12,6   11   13,3   01   15,3   06   12,4   26     4,7   28     4,0   30     1,4   12    -4,5   04/02
Alt Empordà      D4   Roses                         -1,6   15    -4,2   09     2,9   16     4,6   07    7,0   01   13,5   12   13,5   24   15,7   27    8,7   27     2,1   30     3,5   23    -2,5   12    -4,2   09/02
Alt Empordà      U2   Sant Pere Pescador            -3,5   15    -6,1   09    -0,2   02     2,6   07    5,8   01   10,3   12    9,6   24   12,7   27    8,0   27    -0,2   30     1,9   23    -3,5   12    -6,1   09/02
Alt Empordà      W2   Torroella de Fluvià           -4,0   15    -6,7   09    -1,3   02     1,6   07    3,4   02    9,5   12    9,5   24   12,6   27    6,4   27    -0,6   30     0,9   30    -4,2   12    -6,7   09/02
Alt Empordà      W3   Ventalló                      -5,0   15    -6,8   09    -0,7   02     1,9   07    4,3   01   10,2   12   10,6   24   12,5   27    6,9   27    -0,7   30    -0,8   30    -5,2   12    -6,8   09/02
Alt Penedès      WP   Canaletes                     -1,0   14    -5,3   12     1,6   07     3,1   17    5,7   03   11,2   13   12,1   02   13,7   31    9,0   27     1,8   29    -0,8   30    -0,6   02    -5,3   12/02
Alt Penedès      DI   Font-rubí                     -1,1   29    -4,9   12     2,0   08     4,4   17    6,9   01   11,6   09   11,8   02   15,1   31   10,0   26     0,3   29    -0,3   30    -0,3   02    -4,9   12/02
Alt Penedès      W4   la Granada                    -0,9   31    -5,4   13     1,0   07     3,7   17    5,9   01   11,1   13   12,1   02   13,5   31    9,0   26     1,7   29    -0,9   30    -0,3   02    -5,4   13/02
Alt Penedès      U3   Sant Martí Sarroca            -4,1   14    -7,2   13    -0,3   08     3,0   07    4,6   03   11,2   12   11,4   02   13,2   31    8,2   26    -0,6   29    -1,1   30    -4,3   02    -7,2   13/02
Alt Penedès      WY   Sant Sadurní d'Anoia          -2,7   31    -5,7   13    -0,3   08     2,4   07    4,7   01   10,7   12   12,0   02   13,8   31    8,0   27     1,6   30    -2,2   30    -2,8   02    -5,7   13/02
Alt Urgell       CD   la Seu d'Urgell               -6,9   15   -10,7   12    -4,6   06    -1,5   17    2,1   01    6,3   12    7,5   02    7,2   31    3,1   27    -3,0   29    -4,0   30    -8,4   12   -10,7   12/02
Alt Urgell       W5   Oliana                        -6,6   31   -12,0   12    -4,3   08    -1,1   14    1,4   01    7,8   12    9,6   02   11,2   26    7,4   26    -3,1   29    -4,5   30    -6,8   10   -12,0   12/02
Alt Urgell       CJ   Organyà                       -8,2   14    -8,8   05    -2,4   19    -0,9   20    1,1   01    6,6   12    9,9   02   10,4   31    5,6   27    -2,2   30    -1,7   30    -7,8   12    -8,8   05/02
Alta Ribagorça   Z2   Boí (2.535 m)                -14,3   29   -23,0   03   -13,6   06   -11,5   16   -7,2   01   -1,8   12    0,7   01   -2,0   31   -3,5   26   -14,2   28   -12,9   29   -11,5   06   -23,0   03/02
Alta Ribagorça   CT   el Pont de Suert             -10,3   15   -11,8   21    -6,4   07    -3,4   17   -0,1   01    3,5   12    5,4   15    5,2   31    1,5   27    -4,9   29    -6,7   30    -9,6   12   -11,8   21/02
Anoia            CE   els Hostalets de Pierola      -2,0   14    -5,1   13     1,3   07     3,4   17    5,8   01   12,4   12   12,2   02   13,1   31   10,0   27     1,2   29    -0,2   30    -1,9   02    -5,1   13/02
Anoia            XB   la Llacuna                    -6,2   14    -8,2   12    -2,8   07     1,1   17    2,4   03    6,4   13    9,8   24   10,2   31    5,0   27    -1,5   29    -3,2   30    -3,9   01    -8,2   12/02
Anoia            XA   la Panadella                  -3,9   30   -10,1   03    -2,2   06    -1,4   17    4,2   01    8,3   12    8,5   02    9,5   31    7,5   27    -1,2   28    -2,0   30    -4,4   02   -10,1   03/02
Anoia            H1   Òdena                         -5,6   14    -8,7   13    -4,2   07     0,3   17    2,3   01    7,9   13   10,4   02   12,2   31    5,0   27    -0,7   30    -3,3   30    -4,8   02    -8,7   13/02
Bages            WW   Artés                         -5,9   14   -10,3   11    -4,9   06    -2,1   17    2,2   01    9,0   12   10,4   24   10,6   31    5,0   27    -2,6   29    -5,0   30    -5,6   02   -10,3   11/02
Bages            U4   Castellnou de Bages           -5,5   14    -7,5   03    -1,7   06     1,3   17    3,8   01    9,6   12   11,3   02   11,6   31    6,7   27    -0,3   29    -2,9   30    -3,8   02    -7,5   03/02
Bages            R1   el Pont de Vilomara           -5,3   14    -9,6   13    -3,0   07    -0,6   17    2,9   01    9,6   13   11,3   02   12,3   31    6,0   27    -1,2   29    -3,4   30    -5,0   02    -9,6   13/02
Bages            WN   Montserrat - Sant Dimes       -0,3   29    -7,4   12     0,4   19     1,8   17    5,3   21    9,5   12    9,5   02   11,5   31    8,6   26     2,4   29    -0,1   30    -1,0   06    -7,4   12/02
Bages            CL   Sant Salvador de Guardiola    -6,3   30   -10,1   13    -4,2   07     0,3   17    1,6   01    7,8   13    9,9   24    9,9   31    4,7   27    -1,5   30    -5,0   30    -6,4   02   -10,1   13/02
Baix Camp        U5   Prades - los Hortals          -6,6   30   -12,9   12    -5,8   09    -2,7   17    0,7   01    6,8   09    4,9   02    7,8   31    3,8   02    -3,1   29    -5,0   30    -6,6   01   -12,9   12/02
Baix Camp        W6   Riudoms                        0,0   13    -3,2   03     2,7   01     4,9   07    6,3   01   13,9   13   14,8   02   16,1   31   10,7   26     4,1   28     3,7   30     1,6   10    -3,2   03/02
Baix Camp        U6   Vinyols i els Arcs            -1,1   15    -2,1   03     1,9   15     4,7   07    6,9   01   15,6   02   15,1   01   17,3   31   11,7   26     6,4   28     4,6   30     2,4   10    -2,1   03/02
Baix Ebre        U7   Aldover                        0,4   31    -2,0   03     3,7   01     4,0   07    6,6   01   13,4   09   14,8   02   17,1   31   12,2   27     4,5   30     3,7   30     1,0   10    -2,0   03/02
Baix Ebre        DB   el Perelló                    -0,2   15    -2,8   03     3,2   07     6,0   17    7,4   01   15,5   09   15,3   02   16,9   31   12,0   29     5,0   30     3,5   30     1,7   01    -2,8   03/02
Baix Ebre        U9   l'Aldea                       -1,3   13    -1,2   04     3,5   01     5,2   07    7,1   01   14,3   09   15,5   01   18,2   31   11,4   27     6,0   30     5,6   30     0,6   10    -1,3   13/01
Baix Ebre        UA   l'Ametlla de Mar               1,1   15    -2,2   03     4,5   23     5,0   07    6,6   01   14,9   09   15,2   01   17,1   31   11,7   27     4,8   30     4,1   30     2,4   12    -2,2   03/02
Baix Ebre        X5   PN dels Ports                 -4,5   30   -11,3   04    -4,0   07    -2,8   17    0,2   01    5,8   09    7,4   01    8,0   31    4,8   27    -2,6   29    -4,6   30    -5,8   01   -11,3   04/02
Baix Empordà     DO   Castell d'Aro                 -1,7   15    -7,4   05    -0,4   06     2,2   17    4,9   01   11,2   12   12,1   24   13,6   31    9,1   27    -0,7   29    -1,5   30    -3,0   12    -7,4   05/02
Baix Empordà     DF   la Bisbal d'Empordà                    -3,2   15    -6,8   12    -2,4   06    0,5   17    4,6   01   11,1   12   10,3   24   11,6   31    7,7   27    -1,0   29    -2,2   30    -4,2   12    -6,8   12/02
Baix Empordà     UB   la Tallada d'Empordà                   -4,1   15    -7,1   12    -2,0   06    1,8   17    4,8   01   11,9   12   10,8   24   12,4   31    7,2   27    -0,5   30    -2,2   30    -5,1   12    -7,1   12/02
Baix Empordà     UC   Monells                                -3,7   15    -8,0   13    -3,2   06   -1,2   17    2,7   01   10,5   13   10,5   24    8,8   31    6,2   27    -2,1   29    -2,5   30    -4,8   12    -8,0   13/02
Baix Empordà     UD   Serra de Daró                          -3,2   15    -6,8   12    -1,7   06    0,9   17    4,6   01   11,7   12   10,1   24   11,5   31    7,3   27     0,5   30    -1,7   30    -3,8   12    -6,8   12/02
Baix Empordà     UE   Torroella de Montgrí                   -1,8   15    -5,6   12    -1,1   02    2,5   07    5,5   01   12,6   12   11,8   24   14,3   27    8,4   27     1,0   30    -0,5   30    -3,4   12    -5,6   12/02
Baix Llobregat   UF   Begues - PN del Garraf                  0,1   29    -5,8   04     2,5   06    3,1   17    6,4   21   11,8   12   12,3   01   14,2   31   10,1   26     1,8   28     0,1   30    -0,4   02    -5,8   04/02
Baix Llobregat   XL   el Prat de Llobregat                    0,6   30    -4,6   05     2,1   06    5,5   07    8,5   01   12,4   12   14,8   02   16,8   31    9,9   26     3,3   29     1,9   30     0,9   09    -4,6   05/02
Baix Llobregat   D3   Vallirana                               0,6   29    -3,1   03     4,1   07    5,4   17    6,7   01   12,9   12   13,9   02   15,9   31   11,3   27     4,7   29     1,9   30     0,4   01    -3,1   03/02
Baix Llobregat   UG   Viladecans                              1,2   30    -4,1   05     3,8   08    6,2   11    8,4   01   15,0   16   15,4   02   17,5   31   12,1   26     4,2   29     2,2   30     1,1   02    -4,1   05/02
Baix Penedès     WZ   Cunit                                  -1,9   30    -4,7   13     3,1   10    2,2   17    7,1   01   13,0   12   13,5   02   14,4   31   11,3   26     1,8   29     1,4   30    -1,6   02    -4,7   13/02
Baix Penedès     UH   el Montmell                            -0,7   29    -4,7   03     1,9   07    3,9   17    5,4   01   11,4   12   10,0   01   13,8   31    9,8   27     1,5   29     0,4   30     0,4   02    -4,7   03/02
Baix Penedès     D9   el Vendrell                            -1,4   30    -4,2   12     1,2   10    5,3   07    6,4   02   12,9   12   13,2   02   17,7   08   10,7   26     4,3   29     1,1   30     0,1   11    -4,2   12/02
Baix Penedès     WO   la Bisbal del Penedès                  -5,4   14    -5,9   13    -1,3   10    4,5   02    3,8   01   11,6   15   12,9   24   14,6   08    7,0   27     0,9   30    -2,1   30    -2,9   01    -5,9   13/02
Barcelonès       WU   Badalona - Museu                        2,2   14    -0,8   04     4,9   07    6,7   17    9,9   01   16,7   12   15,9   02   17,2   31   14,2   27     5,6   29     2,9   30     2,4   02    -0,8   04/02
Barcelonès       X4   Barcelona - el Raval                    5,5   30     0,6   04     7,9   09    9,1   17   11,6   01   17,6   12   16,6   01   19,4   30   16,3   29     7,6   29     5,6   30     4,5   02     0,6   04/02
Barcelonès       D5   Barcelona - Observatori Fabra           1,0   30    -4,7   03     4,5   07    4,5   17    7,7   21   12,7   12   13,4   02   15,2   31   12,4   27     3,2   28     1,9   30     0,5   02    -4,7   03/02
Barcelonès       X8   Barcelona - Zona Universitària          1,9   14    -1,8   04     4,8   06    6,1   17    7,6   01   14,5   12   14,6   01   16,8   31   13,3   27     5,4   29     2,3   30     2,1   02    -1,8   04/02
Barcelonès       X2   Barcelona - Zoo                         3,1   13    -2,3   05     5,1   10    8,5   07   10,1   01   15,9   12   16,6   02   18,0   31   14,8   02     6,8   29     4,3   30     2,2   02    -2,3   05/02
Berguedà         UI   Gisclareny                             -5,1   16   -12,5   04    -4,1   05   -2,7   17   -0,6   01    5,7   13    7,4   02    6,1   31    3,2   26    -2,8   29    -5,1   30    -5,6   12   -12,5   04/02
Berguedà         WV   Guardiola de Berguedà                  -7,4   14   -11,7   12    -5,8   07   -2,9   14    0,6   02    5,7   12    6,3   02    6,3   31    0,9   27    -4,4   30    -5,7   30    -8,4   01   -11,7   12/02
Berguedà         CR   la Quar                                -3,5   29   -11,5   12    -1,8   07   -2,3   17    1,2   01    5,7   12   10,0   15    8,9   31    5,0   27    -1,9   29    -2,7   30    -4,7   01   -11,5   12/02
Berguedà         WM   Santuari de Queralt                    -2,4   29    -9,1   04    -0,8   06   -0,2   11    2,9   01    6,2   12    9,2   02    9,7   31    7,2   26    -1,0   28    -1,3   30    -2,8   12    -9,1   04/02
Cerdanya         Z9   Cadí Nord (2.143 m) - Prat d'Aguiló   -11,5   30   -19,6   03   -10,4   06   -9,0   17   -4,5   01    1,8   12    2,9   01    0,9   31   -1,0   26   -10,5   28   -11,4   30    -9,2   02   -19,6   03/02
Cerdanya         DP   Das                                   -12,9   14   -16,6   12    -9,7   10   -5,5   14   -2,2   14    0,6   12    2,3   02    3,6   27   -2,8   27    -6,9   30    -8,3   30   -13,5   12   -16,6   12/02
Cerdanya         Z3   Malniu (2.230 m)                      -12,2   29   -20,6   03   -10,7   06   -9,6   16   -5,4   01    0,4   12    2,9   01   -0,2   31   -0,4   27   -12,1   28   -11,3   30    -9,1   02   -20,6   03/02
Conca de B.      W8   Blancafort                             -3,1   19    -8,2   11    -2,8   07    1,9   17    2,9   01   10,7   13   11,8   02   12,5   31    6,2   27    -0,3   30    -1,2   30    -3,1   11    -8,2   11/02
Conca de B.      CW   l'Espluga de Francolí                  -2,0   16    -5,9   04    -0,9   07    2,5   17    2,8   01   11,5   04   10,4   02   13,2   31    6,5   27    -0,3   30    -1,0   30    -3,2   12    -5,9   04/02
Conca de B.      UJ   Santa Coloma de Queralt                -3,4   14    -8,9   03    -1,1   07   -0,4   17    3,4   01    8,3   13    9,2   02   10,7   31    6,7   27    -0,3   28    -1,6   30    -3,4   02    -8,9   03/02
Garraf           UK   Sant Pere de Ribes - PN del Garraf     -0,3   29    -3,8   04     2,8   06    4,2   17    7,1   01   12,9   12   12,4   02   13,2   31   12,0   27     2,6   29     0,3   30     0,2   02    -3,8   04/02
Garrigues        UL   Castelldans                            -4,9   26    -7,0   06    -1,9   10    1,7   07    3,2   01   11,5   15   12,8   03   13,6   31    5,8   27    -0,5   30    -1,5   30    -5,1   12    -7,0   06/02
Garrigues        UM   la Granadella                          -3,4   11    -7,6   03    -2,5   10    0,6   17    2,7   01   10,9   13   10,8   02   11,5   31    6,2   02     1,1   29    -0,9   30    -3,4   12    -7,6   03/02
Garrotxa         W9   la Vall d'en Bas                       -6,3   14   -10,9   13    -5,8   07   -2,2   17    1,7   01    8,8   12    6,7   24    8,5   31    4,3   27    -4,3   29    -5,0   30    -6,6   09   -10,9   13/02
Garrotxa         DC   Olot                                   -4,9   15    -9,9   12    -3,6   07   -1,8   17    2,6   01    9,0   12    9,9   24    9,6   31    5,5   27    -3,3   29    -3,9   30    -5,9   12    -9,9   12/02
Gironès          UN   Cassà de la Selva                      -4,2   15   -10,7   05    -3,0   06    0,5   17    1,9   01    8,8   12   11,0   24   10,5   31    6,7   27    -3,2   29    -4,4   30    -5,3   12   -10,7   05/02
Gironès          UO   Fornells de la Selva                   -5,8   15   -10,4   13    -4,9   07   -1,5   17    2,2   01    9,3   12    9,2   24   10,3   31    6,1   27    -3,5   29    -4,3   30    -6,3   12   -10,4   13/02
Gironès          XJ   Girona                                 -5,1   15    -9,6   13    -4,0   07   -1,6   17    3,1   01   10,2   12    9,7   24   10,4   31    5,7   27    -3,1   29    -3,8   30    -5,7   12    -9,6   13/02
Gironès          WF   Vilablareix                            -5,2   15    -9,9   13    -4,3   07   -1,7   17    3,0   02    9,0   12    9,7   24   11,7   31    5,7   27    -2,8   29    -2,8   30    -4,6   12    -9,9   13/02
Maresme          UP   Cabrils                                 1,6   30    -2,6   11     3,2   07    6,7   17    8,5   01   13,9   12   15,1   02   15,9   31   13,3   26     3,7   28     3,0   30     2,6   12    -2,6   11/02

Если вы знаете, как правильно управлять текстовым редактором, очень легко и быстро исправить этот текст, поэтому он будет плавно импортироваться Excel...