Analyse der Smart Voting-Website und der neuen API auf der CEC-Website

Bild



Am 13. September 2020 fand in Russland ein einziger Wahltag statt. In einigen Regionen hat die Opposition die Strategie des „Smart Voting“ angewendet , bei der oppositionelle Wähler für einen einzelnen Kandidaten stimmen, der die höchste Chance hat, einen Vertreter der Behörden zu besiegen.



Zum zweiten Mal in Folge hat die Auswahl der Kandidaten für "Smart Voting" zu Diskussionen über das Thema Transparenz geführt. Darüber hinaus bin ich persönlich verwirrt über die Schwierigkeiten bei der Zusammenfassung der Strategie, mit der unabhängige Analysten konfrontiert sein könnten. Die Organisatoren der UMG veröffentlichen keine detaillierten Ergebnisse der Strategie, sondern nur Diagramme, aus denen hervorgeht, wie viele Oppositionskandidaten in das Regionalparlament eingetreten sind.



Auf der Website von "Smart Voting"Sie können keine Liste der unterstützten Kandidaten erhalten, indem Sie beispielsweise Stadt und Bezirk angeben. Wenn jemand Daten über die Region sammeln möchte, muss er die monotone Arbeit der Adressauswahl für jeden Distrikt erledigen.



In keinem Fall mache ich den Entwicklern der UMG-Website Vorwürfe, sie verfügt über alle erforderlichen Funktionen, um die Abstimmungsstrategie umzusetzen. Aufgrund der Tatsache, dass 2019 niemand an der Erhebung und Veröffentlichung detaillierter Daten zu den Ergebnissen der UMG (außerhalb der Wahlen in Moskau) beteiligt war, beschloss ich bei diesen Wahlen, die Initiative selbst in die Hand zu nehmen.



Das Ergebnis ist eine Übersichtstabelle wie diese . In diesem Artikel werde ich Ihnen erklären, wie der angegebene Datensatz erhalten wurde , wie Informationen von den Smart Voting-Websites und dem neuen CEC- Webdienst gesammelt wurden .



Bild



Smart Voting Site



Lassen Sie uns zunächst sehen, welche Daten wir von der Smart Voting-Site extrahieren können. Auf der Hauptseite der Site befindet sich ein Feld zur Eingabe der Registrierungsadresse des Benutzers. Wenn Sie eine Zeichenfolge eingeben, wird eine Liste der vorgeschlagenen Adressen im folgenden Format angezeigt:



Bild




Wenn Sie eine der vorgeschlagenen Adressen auswählen, werden wir zu der Seite des Wahllokals weitergeleitet, an die die ausgewählte Adresse angehängt ist:



Bild


Auf der Seite werden die Wahlkämpfe aufgelistet, die auf dieser Website stattfinden. Für jede Kampagne gibt es eine Liste von Kandidaten, für die sie zur Abstimmung angeboten werden:



Bild


In diesem Fall sehen wir die Wahl des Gouverneurs, für die die UMG keinen Oppositionskandidaten angegeben hat. Dies liegt an der Tatsache, dass die Wahlen der Gouverneure in zwei Runden stattfinden und es keine Rolle spielt, für welchen der Oppositionskandidaten die Wähler in der ersten Runde stimmen werden.

Wir sehen auch drei Kandidaten gleichzeitig, für die ihnen angeboten wird, bei den Wahlen zum Stadtparlament zu stimmen. Dies ist darauf zurückzuführen, dass die Wahlen in Sotschi aus mehreren Mitgliedern bestehen.

In allen anderen Wahlkämpfen, die in diesem Jahr an der UMG beteiligt waren, gab es nur Wahlkreise mit nur einem Mitglied.



Schauen wir uns den Seitencode an und stellen fest, dass alle beschriebenen Daten in einem praktischen JSON-Format erfasst werden. In dem Element mit id = "__ NEXT_DATA__", mit dem die Seite gezeichnet wird, gibt es Informationen über das Wahllokal, die entsprechenden Wahlkämpfe und Kandidaten:



Inhalt des Elements __NEXT_DATA__
{
   "props":{
      "pageProps":{
         "id":"440384",
         "settings":{
            "id":1,
            "share_photo":"/ganimed-media/share_photo/smartvote_sharepic_1200x628.jpg",
            "video_on_main_page":"https://youtu.be/w8gapDGwWMY",
            "fake_mode":false,
            "title_share":",    ",
            "text_share":" ,      —    « ».   — .",
            "telegram_bot_link":"https://tlinks.run/smartvotebot",
            "viber_bot_link":"viber://public?id=smartvote",
            "facebook_bot_link":"https://facebook.com/umnoegolosovanie/",
            "alice_link":null,
            "vk_bot_link":null
         },
         "serverData":{
            "commission":{
               "id":440384,
               "number":"4317",
               "address":"354340,  ,  ,  ,   , 24",
               "descr":"   № 49 . .. ",
               "lat":"43.425923",
               "lon":"39.920152",
               "region_id":26,
               "region_intid":"135637827259064320000372513"
            },
            "campaigns":[
               {
                  "id":26,
                  "code":"krasnodar-gub-2020",
                  "title":"   ",
                  "is_regional":true,
                  "ready_date":null,
                  "district":{
                     "id":458,
                     "code":"oik-0",
                     "name":"0",
                     "leaflet":""
                  },
                  "candidates":[
                     {
                        "id":998,
                        "name":"  ",
                        "share_image":"/elections-api-media/share/26/998.png",
                        "anticandidate":true,
                        "self_nominated":false,
                        "has_won":false,
                        "has_second_round":false,
                        "party":{
                           "title":" ",
                           "antiparty":true
                        }
                     }
                  ]
               },
               {
                  "id":28,
                  "code":"krasnodar-sochi-gorduma-2020",
                  "title":"    ",
                  "is_regional":false,
                  "ready_date":null,
                  "district":{
                     "id":526,
                     "code":"oik-2",
                     "name":"2",
                     "leaflet":"/elections-api-media/28/526-1334-1335-5385.pdf"
                  },
                  "candidates":[
                     {
                        "id":1334,
                        "name":"  ",
                        "share_image":"/elections-api-media/share/28/1334.png",
                        "anticandidate":false,
                        "self_nominated":true,
                        "has_won":false,
                        "has_second_round":false,
                        "party":null
                     },
                     {
                        "id":1335,
                        "name":"  ",
                        "share_image":"/elections-api-media/share/28/1335.png",
                        "anticandidate":false,
                        "self_nominated":true,
                        "has_won":false,
                        "has_second_round":false,
                        "party":null
                     },
                     {
                        "id":5385,
                        "name":"  ",
                        "share_image":"/elections-api-media/share/28/5385.png",
                        "anticandidate":false,
                        "self_nominated":false,
                        "has_won":false,
                        "has_second_round":false,
                        "party":{
                           "title":"",
                           "antiparty":false
                        }
                     }
                  ]
               }
            ]
         },
         "error":null,
         "currentUrl":"https://votesmart.appspot.com/candidates/440384"
      }
   },
   "page":"/candidates/[id]",
   "query":{
      "id":"440384"
   },
   "buildId":"U8hjaoxZw8TINu-DU_Ixw",
   "runtimeConfig":{
      "HOST":"https://votesmart.appspot.com"
   },
   "isFallback":false,
   "customServer":true,
   "gip":true
}




Für das Wahllokal sind die Nummer (Nummer) des entsprechenden PEC und seine Kennung in der Datenbank der UMG-Website angegeben. Id = 440834 stimmt mit der in der Seiten-URL gefundenen Nummer überein (/ Kandidaten / 440834).



Können wir bei Kenntnis der PEC-Nummer und der Region die Provisionskennung auf der UMG-Website berechnen? Ich konnte keine offensichtliche Abhängigkeit finden, da die Bezeichner ziemlich chaotisch verteilt sind:

Sotschi, PEC # 4512 -> id = 440834

Sotschi, PEC # 4513 -> id = 441403

Sotschi, PEC # 4514 -> id = 1781216



So sammeln Sie eine Liste von Zahlenreflexionen PEC in ID-Seiten? Es klingt äußerst ineffizient, alle Arten von Kennungen von 1 bis 2.000.000 zu durchlaufen und zu überprüfen. Die meisten dieser Kennungen funktionieren nicht.



Wenn wir jedoch eine Liste mit Adressen haben, können wir relativ einfach eine Liste der relevanten Wahllokale zusammenstellen. Wenn Sie auf dem Startbildschirm eine Zeichenfolge eingeben, wird vom Server eine Liste geeigneter Adressen zusammen mit den entsprechenden Provisionskennungen zurückgegeben:



Suchen Sie nach einer Site nach Adresse



https://votesmart.appspot.com/api/v1/cik/addresses?query=ADDRESS


  • ADRESSE - Adresse, vorzugsweise im Format "Betreff, Stadt, Straße, Haus". Es ist auch ohne Abkürzungen "Straße", "d." Wünschenswert, da der Parser auf dem Server sie nicht gut handhabt


Beispielanfrage:



https://votesmart.appspot.com/api/v1/cik/addresses?query= Lenins Smolensk



Abfrageergebnis
{
   "suggestions":[
      {
         "value":" ,  ,  ,  ",
         "data":{
            "fullname":" ,  ,  ,  ",
            "level":"7",
            "region_id":69,
            "commission_id":null,
            "intid":"138474570115456000000347353",
            "path":"135637827259064320000359815,135637827259064320000359819,135637827259064320000359820,138474570115456000000347353",
            "snippet":" ,  <em></em>,  , <em></em> ",
            "score":118.84238
         }
      },
      {
         "value":" ,  ,  ,  , 12",
         "data":{
            "fullname":" ,  ,  ,  , 12",
            "level":"8",
            "region_id":69,
            "commission_id":1124357,
            "intid":"135659820348349440000359937",
            "path":"135637827259064320000359815,135637827259064320000359819,135637827259064320000359822,135659820348349440000359708,135659820348349440000359937",
            "snippet":" ,  <em></em>,  , <em></em> , 12",
            "score":115.14931
         }
      },
...
   ]
}




Wo kann ich eine Liste mit Adressen zum Extrahieren von Daten von der Site erhalten? Die Aufzählung der Datenbank aller Adressen im Land scheint eine ineffektive Lösung zu sein, da wir zur Lösung unseres Problems nur eine Adresse pro Wahlkreis benötigen.



Jeder Wahlkreis hat durchschnittlich 2 bis 8 Bezirke. Auch wenn die Adresse eines Wahllokals in seltenen Fällen nicht dem Wahlkreis entspricht, zu dem es gehört, stelle ich die folgende Hypothese auf: Wenn Sie die PEC-Adressen auf der UMG-Website durchgehen, können Sie Informationen zu jedem Wahlkreis sammeln.



Mit dieser Hypothese konnte ich später Informationen zu fast allen Wahlkreisen sammeln. Aufgrund der Heterogenität des Adressformats in der Datenbank der Wahlkommissionen musste ich nur die Adressen von 10 von 1100 Wahlkreisen manuell auswählen.



Im Internet finden Sie eine regelmäßig aktualisierte Datenbank der Wahlkommissionen der Russischen Föderation mit Informationen zu den Adressen und sogar zur Zusammensetzung der PECs. Aus Gründen der Relevanz und Zuverlässigkeit der Daten (und auch, weil ich mit dem Format eines bestimmten Felds nicht zufrieden war) habe ich mich entschlossen, die Adressliste selbst zu sammeln, da die CEC-Website, wie sich herausstellte, über alle dafür erforderlichen Funktionen verfügt.



Neuer CEC-Webdienst. API-Methoden



GAS "Vybory" ist ein 1995 entwickeltes automatisiertes System zur Vorbereitung und Durchführung von Wahlen und Referenden in der Russischen Föderation.



Wenn Sie jemals an den Fortschritten des Wahlkampfs interessiert waren, sind Sie wahrscheinlich auf diese Website gestoßen , die anhand der grundlegenden Informationen des SAS-Systems "Wahlen" veröffentlicht wird, einschließlich des Fortschritts der Stimmenzahl, noch bevor die



Bild



Wahlergebnisse genehmigt wurden : Und wenn früher, um die Datenergebnisse der Wahlergebnisse abzurufen Auf dieser Website wurde in den Tagen der Abstimmung über Änderungen der Verfassung plötzlich ein Captcha auf der Website angezeigt . Captcha ist sehr hartnäckig. Es wird angezeigt, wenn Sie zu jeder Seite der Site gehen:



Bild


Wie Sie selbst visuell beurteilen können, ist das Captcha natürlich sehr einfach, und sicherlich hat bereits jemand Wege gefunden, es zu umgehen. Anstatt maschinelles Lernen zu betreiben , habe ich mich einem neuen Abschnitt auf der CEC-Website zugewandt, über den nur sehr wenige Menschen Bescheid wissen: Digitale Dienste



Bild



Dieser Abschnitt erschien nur während der Abstimmung über Änderungsanträge und enthält mehrere Webdienste, die über HTTP verfügbar sind Anforderungen kommunizieren mit der internen API, um Daten vom GAS "Vybory" -System zu empfangen. Der Habr-Benutzer hat diese Funktionalität bereits beachtet . Lassen Sie es uns genauer betrachten.



Im Folgenden werden die Hauptanforderungen der neuen API beschrieben, die in diesem Projekt verwendet wurden:



Jede Datenstruktur im System enthält einen VRN- Schlüssel- eine eindeutige Kennung für die Entität, sei es eine Site, eine Kampagne, ein Distrikt oder ein Kandidat .




PEC-Informationen



http://cikrf.ru/iservices/voter-services/committee/subjcode/SUBJECT_CODE/num/COMMITTEE_NUM


  • SUBJECT_CODE - RF- Betreffcode
  • COMMITTEE_NUM - PEC-Nummer


Beispielanfrage:



http://cikrf.ru/iservices/voter-services/committee/subjcode/ 01 / num / 2



Abfrageergebnis
{
   "vrn":"4014001117979",
   "name":"   №2",
   "subjCode":"01",
   "numKsa":"01T001",
   "vid":"5",
   "address":{
      "address":"385200,  ,   ,  ,   .., 16",
      "descr":"  №1",
      "phone":"8-87772-9-23-72",
      "lat":"44.882893",
      "lon":"39.187187"
   },
   "votingAddress":{
      "address":"385200,  ,   ,  ,   .., 16",
      "descr":"  №1",
      "phone":"8-87772-9-23-72",
      "lat":"44.882893",
      "lon":"39.187187"
   }
}







Informationen zu Wahlkämpfen vor Ort



http://cikrf.ru/iservices/voter-services/vibory/committee/COMMITTEE_VRN


  • COMMITTEE_VRN - PEC-Kennung


Anforderungsbeispiel:



http://cikrf.ru/iservices/voter-services/vibory/committee/ 4544028162533



Abfrageergebnis
[
   {
      "vrn":"100100163596966",
      "date":"2020-07-01",
      "name":"         ",
      "subjCode":"0",
      "pronetvd":null,
      "vidvibref":"0"
   },
   {
      "vrn":"25420001876696",
      "date":"2020-09-13",
      "name":"       ",
      "subjCode":"54",
      "pronetvd":"0",
      "vidvibref":"2"
   },
   {
      "vrn":"4544220183446",
      "date":"2020-09-13",
      "name":"        ",
      "subjCode":"54",
      "pronetvd":null,
      "vidvibref":"2"
   }
]





Liste der Wahlkreise



http://cikrf.ru/iservices/sgo-visual-rest/vibory/CAMPAIGN_VRN/tvd


  • CAMPAIGN_VRN - Kampagnen-ID


Beispiel anfordern:



http://cikrf.ru/iservices/sgo-visual-rest/vibory/ 457422069597 / tvd



Abfrageergebnis
{
   "_embedded":{
      "tvdDtoList":[
         {
            "vrn":457422069601,
            "namtvd":"    ",
            "namik":"    ",
            "numtvd":"0",
            "vidtvd":"ROOT",
            "_links":{
               "results":{
                  "href":"http://cikrf.ru/iservices/sgo-visual-rest/vibory/457422069597/results/457422069601/proportion"
               }
            }
         },
         {
            "vrn":457422069602,
            "namik":"   № 1",
            "numtvd":"1",
            "vidtvd":"OIK",
            "_links":{
               "results":{
                  "href":"http://cikrf.ru/iservices/sgo-visual-rest/vibory/457422069597/results/457422069602/major"
               }
            }
         },
         ...
      ]
   },
   "_links":{
      "self":{
         "href":"http://cikrf.ru/iservices/sgo-visual-rest/vibory/457422069597/tvd"
      }
   }
}




NUMTVD ist die Kreisnummer . Die Zahl Null ist normalerweise für die Ergebnisse eines einzelnen Distrikts verantwortlich. Wenn beispielsweise Wahlen in einem gemischten System abgehalten werden, ist der "Null-Wahlkreis" für die Abstimmung in einem proportionalen System verantwortlich. Der Rest der Wahlkreise besteht aus einem oder mehreren Mitgliedern.



Wie Sie sehen können, enthält die Datenstruktur auch einen Link, über den die Wahlergebnisse ermittelt werden können. Der Link wird bereits vor der Veröffentlichung der Abstimmungsergebnisse erstellt.






Liste der am Wahlkampf teilnehmenden Kandidaten



http://cikrf.ru/iservices/sgo-visual-rest/vibory/CAMPAIGN_VRN/candidates/?page=PAGE_NUM&numokr=NUMTVD


  • CAMPAIGN_VRN - Kampagnen-ID
  • PAGE_NUM - Listenseitenzahl
  • NUMTVD - Kreisnummer (optional)


Beispiel anfordern:



http://cikrf.ru/iservices/sgo-visual-rest/vibory/ 4674220125616 / Kandidaten /? Page = 1 & numokr = 11



Abfrageergebnis
{
   "_embedded":{
      "candidateDtoList":[
         ...
         {
            "index":50,
            "vrn":4674020270868,
            "fio":"  ",
            "datroj":"23.04.1964 00:00:00",
            "vidvig":"",
            "registr":"",
            "vrnio":4674220132098,
            "namio":"    \"     \"   ",
            "numokr":11,
            "tekstat2":"1",
            "_links":{
               "self":{
                  "href":"http://cikrf.ru/iservices/sgo-visual-rest/vibory/4674220125616/candidates/4674020270868"
               }
            }
         },
         {
            "index":56,
            "vrn":4674020269642,
            "fio":"  ",
            "datroj":"15.02.1986 00:00:00",
            "vidvig":"",
            "registr":"  ",
            "namio":"",
            "numokr":11,
            "tekstat2":"1",
            "_links":{
               "self":{
                  "href":"http://cikrf.ru/iservices/sgo-visual-rest/vibory/4674220125616/candidates/4674020269642"
               }
            }
         },
         {
            "index":105,
            "vrn":4674020271181,
            "fio":"  ",
            "datroj":"15.07.1994 00:00:00",
            "vidvig":"",
            "registr":"",
            "vrnio":4674220134054,
            "namio":"     \"   \"",
            "numokr":11,
            "tekstat2":"1",
            "_links":{
               "self":{
                  "href":"http://cikrf.ru/iservices/sgo-visual-rest/vibory/4674220125616/candidates/4674020271181"
               }
            }
         },
         ...
         
      ]
   },
   "_links":{
      "self":{
         "href":"http://cikrf.ru/iservices/sgo-visual-rest/vibory/4674220125616/candidates?page=1&numokr=11"
      }
   },
   "page":{
      "size":20,
      "totalElements":9,
      "totalPages":1,
      "number":1
   }
}




Die Seitenstruktur enthält die Gesamtzahl der Seiten. Sie kann verwendet werden, um zu bestimmen, wann Sie die letzte Seite erreichen (oder anhand einer leeren Liste, die vom Server zurückgegeben wird).






Die API enthält andere Methoden, hauptsächlich um mehr Informationen über die Wahlen / Kandidaten zu erhalten. Bei Bedarf können Sie die erforderlichen Anforderungen einfach verfolgen. Jetzt können Sie mit dem Hochladen von Daten beginnen.



Herunterladen von Daten von der CEC-Website



Bevor mit dem Herunterladen der erforderlichen Daten fortgefahren werden konnte, musste eine Liste der Wahlkämpfe erstellt werden, die wir im Projekt verwenden werden. Tatsache ist, dass „Smart Voting“ nicht überall stattfand, sondern bei Wahlen:

— ,

— ,

— ( 200 )

( 4 ).

//


Ich habe beschlossen, die Nachwahlen zur Staatsduma zu ignorieren, da diese Daten unbedeutend sind. Ein Wikipedia-Artikel am Wahltag half bei der Erstellung einer Liste von Wahlen zu Gemeinderäten , da nur Wahlen in Großstädten aufgelistet wurden.



Ich wandte mich an einen Freund (der mir bei der Umsetzung dieses Projekts geholfen hat, indem er die erforderlichen manuellen Arbeiten durchgeführt hat) und bat ihn, eine Liste mit URLs für die jeweiligen Wahlkämpfe zusammenzustellen, die von der Hauptseite der klassischen CEC-Website stammen . Tatsache ist, dass die URL die Regionen- und Kampagnen-IDs enthält, die wir für die weitere Analyse benötigen.



vybory.izbirkom.ru/region/izbirkom?action=show&vrn=21120001136916&
region=11&prver=1&pronetvd=1


Infolgedessen bestand die Liste aus 43 Wahlkämpfen. Insgesamt fanden am Tag der Einzelwahl mehr als 9000 separate Wahlkämpfe in den Gremien verschiedener Ebenen statt.



Mit der Auswahlliste und den zuvor aufgeführten API-Methoden war es nun einfach, die Daten herunterzuladen. Durch das Schreiben eines Python- Skripts und regelmäßige Anfragen mithilfe des Anforderungsmoduls habe ich die Daten zu Kandidaten und Wahllokalen im ursprünglichen JSON-Format gespeichert.



Das Wichtigste beim Herunterladen von Informationen zu Wahllokalen: Es reicht nicht aus, alle möglichen Nummern ab 1 durchzugehen, bis der Server einen leeren Wert zurückgibt. Tatsache ist, dass die Nummerierung von PECs in der Region unterbrochen werden kann und beispielsweise in der folgenden Form erfolgen kann:

... # 1001 - # 1016, # 1101 - # 1136, 1138 ...

oder:

# 0 - # 700, # 900 - # 1002, 1004 ...

Um die maximale PEC-Nummer in der Region zu bestimmen und keine unnötigen Anfragen zu stellen, habe ich Daten wie folgt gesammelt: Ich habe versucht, Daten zu den ersten 1000 Nummern hochzuladen, und dann überprüft, ob i + 1, i + 5, i + 100, i + 500, i + 1000 Nummern entsprechen jeder PEC (in diesem Fall wird der Download fortgesetzt).



Außerdem empfehle ich, die PEC-Nummer beizubehalten, von der Sie die Daten über das Revier heruntergeladen haben. Tatsache ist, dass die zurückgegebenen Daten nicht die PEC-Nummer enthalten, sondern nur den Namen in der Form: "Precinct Election Commission No. 100" . Der Prozess der Erlangung der ursprünglichen PEC-Nummer, mit dem ich mich später befassen musste, führte zu kurzfristigen Fehlern und Frustrationen. Wie sich herausstellte, hat die Nummerierung im Namen von PECs in einigen Regionen ein anderes Format.



In Udmurtien hatte der Name der PEC beispielsweise die folgende Nummerierung: "011/01, №1 / 02, №1 / 03" in der Region Lipezk : "№01-01, №01-02, №01-03" . In der Region Orenburg bin ich auf eine echte Exotik gestoßen: Es war die einzige Region, in der eine Reihe von Wahlkommissionen nach jemandem benannt wurden. Zum Beispiel "Precinct Election Commission Nr. 1696, benannt nach" Pustovitov Brothers "



Herunterladen von Daten von der Website von "Smart Voting"



Jetzt werden wir für jede gesammelte PEC-Adresse Abstimmungsdaten von der UMG-Website herunterladen. Zuvor sollten einige Funktionen in Betracht gezogen werden (die ich dabei kennengelernt habe):



Zunächst muss berücksichtigt werden, dass die Adressen in der CEC-Datenbank ein anderes Format haben, manchmal sogar in bestimmten Regionen der Regionen. Ich musste die Abkürzungen "d.", "G." und "st." Entfernen, da die Site von "Smart Voting" die Suche nach Adressen für solche Abfragen überhaupt nicht bewältigen konnte. Ich empfehle auch, die Postleitzahl aus der Adresse sowie das manchmal vorkommende Präfix "Russische Föderation" zu entfernen.



Zweitens bietet die UMG-Website einen starken Schutz vor DDoS-Angriffen. Selbst wenn Sie hundert Anfragen im Abstand von 0,3 Sekunden stellen, wird Ihre IP gesperrt. Es wäre möglich, eine Reihe von bezahlten Proxys zu verwenden, aber ich persönlich habe nur kostenlose Proxys und abwechselnde Anfragen von meiner eigenen und einer IP eines Drittanbieters verwendet. Um nicht gebannt zu werden, lag zwischen den Anforderungen ein Intervall von ca. 0,7 Sekunden. Das Herunterladen aller Daten dauerte daher ungefähr einen Tag.



Unter Verwendung der Abfragen aus dem ersten Kapitel lautet der Algorithmus wie folgt:



  1. Formatieren der PEC-Adresse
  2. Fordern Sie eine Liste geeigneter Adressen an
  3. Wir erhalten eine Liste mit Site-Seiten-IDs
  4. Wir überprüfen anhand dieser Kennung, ob wir die Daten über die Website bereits heruntergeladen haben
  5. Laden Sie die HTML-Seite der Site für diesen Bezeichner
  6. Wir extrahieren das Element "__NEXT_DATA__" und speichern die Daten im JSON-Format


Die Seite wurde mit der beautifulsoup4- Bibliothek analysiert .



Dieser Prozess ist nicht fehlerfrei: Normalerweise findet das Skript kein Dutzend Wahllokale in der Region auf der Website oder an der Adresse eines PEC finden Sie Informationen zu einem völlig anderen PEC.



Dies ist kein Problem, da wir für jeden Distrikt nur mindestens eine entsprechende Seite auf der Website finden müssen.



Um die Vollständigkeit der Daten zu überprüfen, schreiben wir ein einfaches Skript, das prüft, ob der von der UMG-Site heruntergeladene Datensatz Informationen zu jedem Wahlkreis enthält. Wenn etwas fehlt, füllen wir den Datensatz manuell auf. Wiederum gab es weniger als 10 solcher Ausnahmesituationen in 1.100 Distrikten.



Kombinieren von Daten von UMG- und CEC-Websites



Zu diesem Zeitpunkt sammeln wir eine bequeme Datenstruktur mit Informationen zu jedem Kandidaten nach Distrikt: Kandidaten-ID, vollständiger Name, Partei, Tag mit Informationen darüber, ob er von der UMG unterstützt wird.



Beispiel eines gesammelten Kandidatendatensatzes
{
    "33": [
        {
            "name": "  ",
            "vrn": 4444032121758,
            "birthdate": "05.05.1958 00:00:00",
            "party": "",
            "smart_vote": 0
        },
        {
            "name": "  ",
            "vrn": 4444032122449,
            "birthdate": "16.11.1977 00:00:00",
            "party": "",
            "smart_vote": 0
        },
        {
            "name": "  ",
            "vrn": 4444032122782,
            "birthdate": "27.02.1996 00:00:00",
            "party": "",
            "smart_vote": 0
        },
        {
            "name": "  ",
            "vrn": 4444032123815,
            "birthdate": "20.11.1991 00:00:00",
            "party": "",
            "smart_vote": 1
        },
        {
            "name": "  ",
            "vrn": 4444032124060,
            "birthdate": "21.07.1996 00:00:00",
            "party": "",
            "smart_vote": 0
        },
        {
            "name": "  ",
            "vrn": 4444032123597,
            "birthdate": "21.05.1974 00:00:00",
            "party": "",
            "smart_vote": 0
        }
    ],
    ...
}




Der Algorithmus ist ziemlich einfach:



  1. Basierend auf dem Datenfeld der UMG-Website erstellen wir eine Liste der unterstützten Kandidaten für jeden Distrikt
  2. Unter Verwendung des Datenarrays von der CEC-Website erstellen wir eine gefilterte Liste der zugelassenen Kandidaten für jeden Wahlkreis
  3. In jedem Distrikt berechnen wir mit vollem Namen die Korrespondenz Candidate-UMG-Candidate-CEC


Natürlich muss ein solch einfacher Algorithmus viele mögliche Problemsituationen berücksichtigen.



Erstens besteht die Möglichkeit, dass es in einem Wahlkreis Kandidaten mit völlig identischen Namen gibt. Glücklicherweise war eine solche Situation unter 5000 Kandidaten nur in einem Fall, und keiner der Kandidaten wurde von der UMG unterstützt.



Zweitens sollte berücksichtigt werden, dass die Datenbank der CEC-Website möglicherweise Fehler enthält. Der häufigste Fehler: Zeilenumbrüche und zusätzliche Leerzeichen im vollständigen Namen. Beim Sammeln von Daten zu den Abstimmungsergebnissen gab es auch eine Situation, in der der Buchstabe "" im Nachnamen durch "e" ersetzt wurde.



Drittens muss die Relevanz der Daten berücksichtigt werden. Die Daten auf der Website der KEK und der UMG wurden bis Samstag geändert und aktualisiert: Einige Kandidaten wurden entfernt / wiederhergestellt, in einigen Wahlkreisen wurde die Unterstützung der UMG geändert.



Um die UMG-Listen zu validieren, wurde ein einfaches Skript geschrieben, das eine Anfrage pro Distrikt stellt (schließlich können wir anhand des von uns gesammelten Datensatzes die Seite für jeden Distrikt eindeutig identifizieren) und prüfen, ob die Namen mit denen übereinstimmen, die wir zuvor erhalten haben.



Eine interessante Aufgabe war es, die Parteien anhand des Namens ihrer Filialen zu identifizieren. Dieser Punkt könnte übersprungen werden, aber ich habe mich dazu entschlossen, die Informationen zu vereinheitlichen. Das Problem ist, dass Kandidaten einer Partei möglicherweise unterschiedliche Namen in der CEC-Datenbank haben. Im Fall des KPRF gab es beispielsweise mehr als 40 Optionen:



  ()    "   " 
-   ""
  
     "   "
...


Die Situation wird zu einem interessanten Analyseproblem, wenn 25 Stapel vorhanden sind und fast jeder für jede Region eine andere Schreibweise hat. Glücklicherweise haben wir mit Hilfe meines Freundes, der mir bei der gesamten manuellen Arbeit geholfen hat, eine Liste von Schlüsselwörtern zusammengestellt, anhand derer die Partei des Kandidaten eindeutig bestimmt wird.



Hochladen der Wahlergebnisse von der CEC-Website



Der gesammelte Datensatz reichte aus, um das ursprüngliche Ziel des Projekts zu erreichen - wir haben Listen der UMG-2020-Kandidaten für jeden Wahlkreis zusammengestellt. Aber wenn es eine technische Möglichkeit gibt, die Wahlergebnisse zu erhalten, warum nicht davon profitieren?






Ergebnisse der Distriktwahlen



http://cikrf.ru/iservices/sgo-visual-rest/vibory/CAMPAIGN_VRN/results/DISTRICT_VRN/major


  • CAMPAIGN_VRN - Kampagnen-ID
  • DISTRICT_VRN - Distrikt-ID


Beispiel anfordern:

http://cikrf.ru/iservices/sgo-visual-rest/vibory/ 457422069597 / results / 457422069602 / major



Abfrageergebnis
{
   "report":{
      "tvd":"",
      "date_sign":"none",
      "vrnvibref":"457422069597",
      "line":[
         {
            "txt":"     ",
            "kolza":"8488",
            "index":"1"
         },
         {
            "txt":" ,   ",
            "kolza":"6700",
            "index":"2"
         },
         ...
         {
            "txt":"  ",
            "kolza":"65",
            "index":"9"
         },
         {
            "txt":"  ",
            "kolza":"1948",
            "index":"10"
         },
         ...
         {
            "delimetr":"1"
         },
         {
            "txt":"  ",
            "numsved":"1",
            "kolza":"112",
            "index":"11",
            "namio":"    ",
            "perza":"5.56",
            "numsvreestr":"4574030258379"
         },
         {
            "txt":"  ",
            "numsved":"2",
            "kolza":"186",
            "index":"12",
            "namio":"     ",
            "perza":"9.24",
            "numsvreestr":"4574030258723"
         },
         {
            "txt":"  ",
            "numsved":"3",
            "kolza":"54",
            "index":"13",
            "namio":"",
            "perza":"2.68",
            "numsvreestr":"4574030258555"
         },
         ...
      ],
      "data_gol":"13.09.2020 00:00:00",
      "is_uik":"0",
      "type":"423",
      "version":"0",
      "sgo_version":"5.6.0",
      "isplann":"0",
      "podpisano":"1",
      "versions":{
         "ver":{
            "current":"true",
            "content":"0"
         }
      },
      "vibory":"        ",
      "repforms":"1",
      "generation_time":"14.09.2020 07:59:21",
      "nazv":"    () ",
      "datepodp":"14.09.2020 05:44:00"
   }
}




Wie Sie sehen, werden die Ergebnisse in Form des Protokolls der Regionalkommission zurückgegeben. Jede Region hat ein anderes Protokollformat und die Anzahl der Einführungszeilen. Daher muss eine sorgfältige Validierung der von Ihnen extrahierten Daten durchgeführt werden.






Als GAS Vybory begann, vorläufige Ergebnisse zu veröffentlichen, war ich mit einer kleinen Enttäuschung konfrontiert. Es stellte sich heraus, dass Sie über die API nur Daten zu den Ergebnissen erhalten können, die offiziell genehmigt wurden. Die vorläufigen Ergebnisse können weiterhin auf der alten Website der Wahlkommission eingesehen werden, jedoch nicht über die neuen Webdienste.



Einen Tag später waren die Ergebnisse von 50% bekannt, und am Ende der Woche wurden die Ergebnisse fast aller Wahlen zusammengefasst. Einige Regionen weigerten sich immer noch, die Ergebnisse zu genehmigen. Zum Zeitpunkt dieses Schreibens sind 7 Tage vergangen, und die Ergebnisse der Wahlen in Tambow wurden noch nicht genehmigt. Darüber hinaus gibt es in einigen Wahlkreisen eine Nachzählung, weshalb diese Ergebnisse auch nicht über die API verfügbar sind.



Schlussfolgerung: API-Methoden sind derzeit nicht geeignet, um Abstimmungsergebnisse umgehend zu erhalten. Sie müssen entweder mehr als eine Woche warten, bis die Ergebnisse genehmigt wurden, oder Sie müssen den alten Standort der Wahlkommission analysieren und einen Weg finden, um das Captcha zu umgehen.



Ich habe es satt, darauf zu warten, dass Wahlen in ~ 30 von 1100 Wahlkreisen genehmigt werden. Deshalb habe ich ein Skript mit der Selenbibliothek geschrieben , das Daten von der klassischen Website der Wahlkommission herunterlädt, und mich gebeten, das Captcha für jede Anfrage manuell zu lösen. Bei einer so geringen Anzahl von Anfragen dauert es nicht lange, ein Captcha manuell zu lösen.



Infolgedessen habe ich die Daten zu den Abstimmungsergebnissen in der folgenden Struktur gesammelt :



Beispiel für Abstimmungsergebnisse des Landkreises
{
...
"33": {
        "candidate_total": {
            "4444032121758": 880,
            "4444032122449": 236,
            "4444032122782": 143,
            "4444032123597": 152,
            "4444032123815": 149,
            "4444032124060": 72
        },
        "is_final": 1,
        "non_valid_votes": 132,
        "registered_voters": 6928,
        "valid_votes": 1632
    },
...
}




Für jeden Wahlkreis habe ich die Gesamtzahl der Wähler auf den Listen (zur Berechnung der Wahlbeteiligung) sowie die Anzahl der gültigen und ungültigen Stimmzettel gespeichert. Die Struktur enthält ein Wörterbuch: Kandidaten-ID -> Die Anzahl der von ihm eingegebenen Stimmen.



Veröffentlichung der Ergebnisse von UMG-2020



Zuerst habe ich die gesammelten Daten im JSON-Format auf GitHub veröffentlicht . Die Daten werden aktualisiert, bis die Ergebnisse in allen Distrikten validiert sind.



Zweitens habe ich mich entschlossen, eine Google-Tabelle zu erstellen, die alle gesammelten Daten in einer praktischen Form für die visuelle Analyse enthält, um auf das Projekt aufmerksam zu machen.



Ich werde nicht auf Details eingehen, es sollten keine Schwierigkeiten (außer beim Studium der Google Sheets-API) auftreten. Ich empfehle diesen Artikel , in dem die Interaktion mit der Google Sheets-API in Python beschrieben wird.



Bild



Als Ergebnis haben wir die folgende Tabelle erhalten, die enthält:





Nachwort



Die Idee für dieses Mini-Projekt kam 3 Tage vor dem Wahltag und ich bin persönlich zufrieden damit, wie ich es geschafft habe, alles in kürzester Zeit zu studieren und umzusetzen (obwohl sich der Code als schrecklich herausstellte).



Ich werde keine Schlussfolgerungen über die Ergebnisse der Smart Voting-Strategie ziehen, sondern nur Tools für Fans von Wahlstatistiken bereitstellen. Ich bin mir sicher, dass es einige unter Ihnen geben wird, und bald werden wir wundervolle Studien mit interessanten Grafiken und Diagrammen sehen.



All Articles