Ściągnąłem protokoły z wyborów do sejmików wojewódzkich jeszcze raz. Punktem wyjścia były indywidualne pliki dla każdej gminy pobrane ze strony samorzad2014.pkw.gov.pl. Te pliki zawierają zsumowane wyniki wyborów dla danej gminy, ale także zawierają adresy URL do plików z wynikami na poziomie poszczególnych komisji (z tej gminy). Mają one adres URL wg schematu:
http://samorzad2014.pkw.gov.pl/357_rady_woj/0/NR_TERYT_GMINY
Mając zestawienie numerów TERYT gmin pobieram indywidualne pliki za pomocą prostego skryptu:
use LWP::Simple;
## Na wejściu lista 6-cyfrowych numerów gmin
while (<>) { $nn++;
chomp();
$File{"$_"}++;
$url = "http://samorzad2014.pkw.gov.pl/357_Sejmiki_wojewodztw/0/$_";
if ( $File{"$_"} > 1 ) {
$file = "./html/$_" . "$File{$_}_" . ".html"; }
else { $file = "./html/$_" . ".html"; }
getstore($url, $file);
print STDERR "$nn = $url => $file... stored\n";
}
Z tych plików wydłubuję numery komisji (które są wartościami atrybutu href do pliku z protokołem i mają postać 321_protokol_komisji_obwodowej/NRKOMISJI) i zapisuję do pliku o strukturze:
020101;321_protokol_komisji_obwodowej/NRKOMISJI
Teraz z plików komisji odczytuję adresy URL protokołów wyborów do sejmików. Ten URL wygląda następująco:
020101;321_protokol_komisji_obwodowej/NRKOMISJI/rdw_COŚTAM
Przy czym COŚTAM to cyfra, np. rdw_5. Problem, że ta cyfra nie zawsze jest taka sama, stąd konieczność przeczytania pliku i odszukania w nim odsyłacza do protokołu wyborów do sejmików. Na szczęście pliki HTML są w miarę proste i do odszukania tego co trzeba wystarczy proste wyrażenie regularne. Poniższy skrypt po odszukaniu odsyłacza pobiera plik protokołu i zapisuje w katalogu ./protokoly_sw/:
#!/usr/bin/perl
use LWP::Simple;
my $log = "protokoly_sw.log";
open (LOG, ">$log") || die ("Nie mogę pisać do $log");
while (<>) { $nn++;
chomp();
($teryt, $postfix, $nrk) = split /[;\/]/, $_;
unless ( -f "./protokoly_sw/$nrk" ) {
$file = "./protokoly_sw/$nrk";
open (LOGP, "./komisje/$nrk");
while (<LOGP>) { chomp();
if (/([^\/]*protokol_komisji.*)">Sejmik/) {## URL do protokołu
$prot_url = $1;
print "$1\n";
last
}
}
close (LOGP);
$url = "http://samorzad2014.pkw.gov.pl/$prot_url";
getstore($url, $file);
print LOG "$nn = $url => $file stored\n";
print STDERR "*** $nn = $url => $file stored\n";
} else { print STDERR "*** $url => $file stored already\n"; }
}
Teraz analizuję pobrane protokoły zapisując informacje do trzech plików .csv: ws2014_komisje.csv ws2014_listy.csv oraz ws2014_kandydaci.csv. Pierwszy zawiera informacje zbiorcze takie jak liczba uprawnionych czy liczba głosów ważnych dla każdej komisji, drugi informacje zbiorcze o liczbie głosów oddanych na każdą listę wyborczą w każdej komisji a trzeci o liczbie głosów oddanych na każdego kandydata w każdej komisji. W związu z tym:
wc -l ws2014_*csv
3062457 ws2014_kandydaci.csv
301876 ws2014_listy.csv
27393 ws2014_komisje.csv
Tj. ws2014_komisje.csv ma 27393 wierszy (i tyle jest komisji); ws2014_listy.csv ma 301876, a ws2014_kandydaci.csv ponad 3mln wierszy (wynik kandydata w każdej komisji, w której był zarejestrowany). Skrypt (nieco uproszczony) wydłubujący potrzebne informacje z pliku protokołu wygląda następująco:
#!/usr/bin/perl
open (LOG, ">>ws2014_log.log");
open (L, ">>ws2014_listy.csv");
open (K, ">>ws2014_kandydaci.csv");
open (X, ">>ws2014_komisje.csv");
$fileName = $ARGV[0];
$fileName =~ s/(\/[^\/]+)$/$1/;
while(<>) {
chomp();
if (/<h2>/) { $mode = 'I';
while (<>) {
chomp();
if (/<div>Kod terytorialny/) { $Teryt = next_line(); }
if (/<div>Numer obwodu/) { $IdO = next_line(); }
if (/<div>Adres/) { $Addr = next_line();
$IdDataFull = "$fileName;$Teryt;$IdO;$Addr";
$IdData = "$fileName;$Teryt;$IdO";
last;
}
}
}
if ($mode eq 'I') {
}
if (/Wyniki wyborów na Kandydatów/) { $mode = 'C' }
if (/ZESTAWIENIE WYNIKÓW/) { $mode = 'S';
while (<>) {
chomp();
## pobieranie informacji nt. komisji
## pominięto kilkanaście wierszy postaci:
## if (/<div>###/) { $xxx = next_line() }
## ...
if (/<div>Liczba kart ważnych/) { $N_karty_wazne = next_line(); }
if (/<div>Liczba głosów ważnych oddanych/) {
$N_glosy_wazne = next_line() ;
print X "$IdDataFull;$N_uprawnieni;$N_karty_otrzymane;$N_karty_niewykorzystane;"
. "$N_karty_wydane;$N_pelnomocnicy;$N_pakiety;$N_karty_wyjete;$karty_z_kopert;"
. "$N_karty_niewazne;$N_karty_wazne;$N_glosy_wazne;$N_glosy_niewazne\n";
last;
}
}
##########
if (/Wyniki wyborów na listy/) {
$mode = 'L' ;
$colNo=0;
%List = ();
$start = 0;
while (<>) {
chomp();
if (/<tbody>/) {$start = 1}
if ($start == 1 ) {
if (/<td[^<>]*>/ ) {
$colNo++;
$List{$colNo} = clean($_);
}
if (/<tr>/) {
$colNo=0;
%List = ();
}
if (/<\/tr>/) {
$line_ = "$IdData;";
for $x (sort keys %List ) { $line_ .= "$List{$x};" }
print L "$line_\n";
}
if (/<\/tbody>/ ) {###
last;
} ##//
}
}
}
###########
if ($mode eq 'C' && /<tr>/) {
$colNo=0;
%Candidate = ();
while (<>) {
chomp();
if (/<table>/) { next } ## skip this line
if (/<\/tr>/ ) {
$line_ = "$IdData;";
for $x (sort keys %Candidate ) { $line_ .= "$Candidate{$x};" }
print K "$line_\n";
last;
} ## //end
if (/<td[^<>]*>/ ) { #############
$colNo++;
$Candidate{$colNo} = clean($_);
}
}
}
}
### ### ###
sub clean {
my $x = shift;
$x =~ s/<[^<>]+>//g;
$x =~ s/^[\t ]+|[\t ]+$//g;
$x =~ s/"//g;
return ($x)
}
sub next_line {
while (<>) {
chomp();
return (clean ($_));
}
}
close(L);
close(K);
close(X);
print LOG "$fileName...\n";
close (LOG);
Kilka minut i po bólu. Teraz sprawdzam czy to co się pobrało i to co było do tej pory z grubsza się zgadza.
#!/usr/bin/perl
$pobranie1="komisje-frekwencja-ws2014.csv"; ## z 2015r
$pobranie2="ws2014_komisje.csv";
open(WX, $pobranie1) || die "cannot open $pobranie1\n";
while (<WX>) {
chomp();
($teryt, $nrk, $nro, $adres, $lwug, $lkw, $lkwzu,
$lgnw, $lgw, $freq, $pgnw) = split /;/, $_;
$LWUG1{"$teryt:$nro"} = $lwug; ## liczba wyborców
$LGW1{"$teryt:$nro"} = $lgw; ## glosy ważne
$ADDR1{"$teryt:$nro"} = $adres; ##
}
close (WX);
### ### ###
open(WY, $pobranie2) || die "cannot open $pobranie2\n";
while (<WY>) {
chomp();
($id, $teryt, $idk, $adres, $uprawnieni, $kartyOtrzymane,
$kartyNiewydane, $kartyWydane, $pelnomocnicy, $pakiety,
$kartyWyjete, $koperty, $kartyNiewazne, $kartyWazne,
$glosy, $glosyNiewazne) = split /;/, $_;
$LWUG2{"$teryt:$idk"} = $uprawnieni;
$LGW2{"$teryt:$idk"} = $glosy;
$ADDR2{"$teryt:$idk"} = $adres;
}
close (WY);
### LWUG1 ma mniej głosów ## ### ### ### ###
for $ik ( sort keys %LWUG1 ) {
if ( ( $LWUG1{$ik} != $LWUG2{$ik} ) ||
($LGW1{$ik} != $LGW2{$ik} )) {
print "$ik $LWUG1{$ik} = $LWUG2{$ik} $LGW1{$ik} = $LGW2{$ik}\n";
}
}
Identyfikatorem komisji na stronach PKW jest 6-cyfrowy numer TERYT + numer komisji (w gminie). Porównanie 26477 komisji pobranych 2015r. z 27446 komisjami pobranymi teraz (+969 komisji) daje w rezultacie:
021901:1 2020 = 2020 914 = 913 021901:2 2189 = 2189 742 = 741 026401:112 2039 = 2039 746 = 744 026401:17 2001 = 2001 536 = 534 026401:178 2073 = 2073 765 = 762 026401:18 1600 = 1600 474 = 473 026401:194 1615 = 1615 637 = 628 026401:215 1457 = 1457 528 = 527 026401:245 2058 = 2058 695 = 697 026401:42 1892 = 1892 504 = 503 026401:70 1823 = 1823 597 = 593 026401:78 1918 = 1918 762 = 760 241004:4 994 = 850 350 = 350 241005:13 1736 = 1736 764 = 762 241005:22 1422 = 1422 569 = 567 241005:6 1441 = 1441 732 = 723 241005:7 1668 = 1668 623 = 621
Czyli dane nie były picowane :-) Dobrze wiedzieć
Pobrane dane są tutaj.
Brak komentarzy:
Prześlij komentarz