Pada 13 September 2020, satu hari pemungutan suara diadakan di Rusia. Di beberapa daerah, oposisi telah menggunakan strategi “Pemungutan Suara Cerdas”, di mana pemilih yang berpikiran oposisi memilih calon tunggal dengan peluang tertinggi mengalahkan perwakilan dari pihak berwenang.
Selama dua tahun berturut-turut, proses pemilihan calon “Smart Voting” menimbulkan diskusi tentang topik transparansi. Selain itu, saya pribadi bingung dengan kesulitan dalam meringkas strategi yang mungkin dihadapi analis independen. Penyelenggara UMG tidak mempublikasikan detail hasil strateginya, melainkan hanya diagram berapa calon oposisi yang masuk ke DPRD.
Di situs "Smart Voting"Anda tidak bisa mendapatkan daftar kandidat yang didukung dengan menentukan, misalnya, kota dan kabupaten. Jika seseorang ingin mengumpulkan data di wilayah tersebut, dia harus melakukan pekerjaan yang monoton dalam memilih alamat untuk setiap distrik.
Dalam hal apa pun saya tidak mencela pengembang situs web UMG, ia memiliki semua fungsi yang diperlukan untuk menerapkan strategi pemungutan suara. Namun karena pada 2019 tidak ada yang terlibat dalam pengumpulan dan publikasi data detail hasil UMG (di luar Pemilu Moskow), dalam pemilu ini saya memutuskan untuk mengambil inisiatif sendiri.
Hasilnya adalah tabel ringkasan seperti ini . Pada artikel ini, saya akan memberi tahu Anda bagaimana kumpulan data tertentu diperoleh , bagaimana informasi dikumpulkan dari situs Smart Voting dan layanan web CEC yang baru .
Situs Voting Cerdas
Pertama, mari kita lihat data apa yang bisa kita ekstrak dari situs Smart Voting. Pada halaman utama situs tersebut terdapat field untuk memasukkan alamat pendaftaran pengguna. Saat Anda memasukkan string, daftar alamat yang disarankan muncul dalam format berikut:

Saat memilih salah satu alamat yang diusulkan, kami dibawa ke halaman TPS, di mana alamat yang dipilih dilampirkan:

Halaman tersebut mencantumkan kampanye pemilihan yang berlangsung di daerah ini. Untuk setiap kampanye, ada daftar calon untuk / melawan siapa mereka ditawarkan untuk memilih:

Dalam kasus ini, kita melihat pemilihan gubernur, yang UMG tidak menunjukkan calon oposisi. Pasalnya, pemilihan gubernur dilakukan dalam dua putaran dan tidak masalah calon oposisi mana yang akan dipilih pemilih pada putaran pertama.
Kami juga melihat tiga kandidat sekaligus, untuk siapa mereka ditawarkan untuk memilih dalam pemilihan parlemen kota. Ini karena pemilu di Sochi memiliki daerah pemilihan beranggotakan banyak orang.
Dalam semua kampanye pemilu lainnya, yang terlibat di UMG tahun ini, hanya ada daerah pemilihan beranggota tunggal.
Mari kita lihat kode halaman dan temukan bahwa semua data yang dijelaskan dikumpulkan dalam format JSON yang nyaman. Di elemen dengan id = "__ NEXT_DATA__", yang digunakan untuk menggambar halaman, terdapat informasi tentang TPS, kampanye pemilu yang sesuai, dan kandidat:
Isi elemen __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
}
Untuk TPS, nomor (number) PEC yang sesuai dan pengenalnya ditunjukkan dalam database situs UMG. Id = 440834 cocok dengan nomor yang ditemukan di url halaman (/ kandidat / 440834).
Bisakah kita, dengan mengetahui nomor PEC dan wilayahnya, menghitung pengidentifikasi komisi di situs UMG? Saya tidak dapat menemukan ketergantungan yang jelas, karena pengenal didistribusikan dengan cukup kacau:
Sochi, PEC # 4512 -> id = 440834
Sochi, PEC # 4513 -> id = 441403
Sochi, PEC # 4514 -> id = 1781216
Cara mengumpulkan daftar refleksi angka PEC di halaman id? Kedengarannya sangat tidak efisien untuk mengulang dan memeriksa semua jenis pengenal dari 1 hingga 2.000.000, sebagian besar pengenal ini tidak berfungsi.
Namun, jika kita memiliki daftar alamat, kita dapat dengan mudah menyusun daftar TPS yang relevan. Saat Anda memasukkan string di layar awal, daftar alamat yang sesuai dikembalikan dari server, bersama dengan pengidentifikasi komisi yang sesuai:
Telusuri situs dengan alamat
https://votesmart.appspot.com/api/v1/cik/addresses?query=ADDRESS
- ALAMAT - alamat, sebaiknya dalam format "Subjek, kota, jalan, rumah". Juga diinginkan tanpa singkatan "street", "d.", Karena parser di server tidak menanganinya dengan baik
Contoh permintaan:
https://votesmart.appspot.com/api/v1/cik/addresses?query= Lenin's Smolensk
Hasil kueri
{
"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
}
},
...
]
}
Di mana saya bisa mendapatkan daftar alamat untuk mengekstrak data dari situs? Menghitung database semua alamat di negara ini tampaknya menjadi solusi yang tidak efektif, karena untuk menyelesaikan masalah kita, kita hanya memerlukan satu alamat per daerah pemilihan.
Setiap daerah pemilihan memiliki rata-rata 2 sampai 8 daerah pemilihan. Meskipun alamat TPS, dalam kasus yang jarang terjadi, mungkin tidak sesuai dengan daerah pemilihannya, saya mengajukan hipotesis berikut: dengan menelusuri alamat PEC di situs web UMG, Anda dapat mengumpulkan informasi tentang setiap daerah pemilihan.
Belakangan, dengan bantuan hipotesis ini, saya berhasil mengumpulkan informasi tentang hampir semua daerah pemilihan. Karena heterogenitas format alamat dalam database komisi pemilu, hanya 10 dari 1100 daerah pemilihan yang harus saya pilih secara manual.
Di Internet, Anda dapat menemukan database komisi pemilu Federasi Rusia yang diperbarui secara rutin , yang berisi informasi tentang alamat dan bahkan komposisi PEC. Tetapi untuk relevansi dan keandalan data yang lebih besar (dan juga karena saya tidak puas dengan format bidang tertentu), saya memutuskan untuk mengumpulkan sendiri daftar alamat, karena, ternyata, situs web CEC memiliki semua fungsi yang diperlukan untuk ini.
Layanan web CEC baru. Metode API
GAS "Vybory" adalah sistem otomatis yang dikembangkan pada tahun 1995, ditujukan untuk persiapan dan pelaksanaan pemilihan dan referendum di Federasi Rusia.
Jika Anda pernah tertarik dengan kemajuan kampanye pemilu, Anda mungkin menemukan situs web ini , yang diterbitkan oleh informasi dasar Sistem SAS "Pemilu", termasuk kemajuan penghitungan suara, bahkan sebelum persetujuan hasil pemilu:
Dan jika sebelumnya untuk mengambil data hasil pemilu menggunakan situs ini, pada hari Voting untuk amandemen Konstitusi , captcha tiba-tiba muncul di situs . Captcha sangat gigih, muncul saat Anda membuka setiap halaman situs:

Karena Anda sendiri dapat mengevaluasi secara visual, captcha tentu saja sangat sederhana, dan tentunya seseorang telah menemukan cara untuk melewatinya. Alih-alih melakukan pembelajaran mesin, saya beralih ke bagian baru di situs web CEC, yang belum banyak diketahui orang: Layanan digital
Bagian ini muncul hanya selama pemungutan suara tentang amandemen dan berisi beberapa layanan web yang, melalui HTTP permintaan berkomunikasi dengan API internal untuk mendapatkan data dari sistem "Vybory" GAS. Pengguna Habr telah memperhatikan fungsi ini. Mari kita pertimbangkan lebih detail.
Berikut ini adalah deskripsi permintaan utama dari API baru yang digunakan dalam proyek ini:
Setiap struktur data dalam sistem berisi kunci VRN- pengenal unik untuk entitas, baik itu situs, kampanye, distrik, atau kandidat .
Informasi PEC
http://cikrf.ru/iservices/voter-services/committee/subjcode/SUBJECT_CODE/num/COMMITTEE_NUM
- SUBJECT_CODE - Kode subjek RF
- COMMITTEE_NUM - Nomor PEC
Contoh permintaan:
http://cikrf.ru/iservices/voter-services/commite/subjcode/ 01 / num / 2
Hasil kueri
{
"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"
}
}
Informasi tentang kampanye pemilu di situs
http://cikrf.ru/iservices/voter-services/vibory/committee/COMMITTEE_VRN
- COMMITTEE_VRN - pengenal PEC
Contoh permintaan:
http://cikrf.ru/iservices/voter-services/vibory/commite/ 4544028162533
Hasil kueri
[
{
"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"
}
]
Daftar daerah pemilihan
http://cikrf.ru/iservices/sgo-visual-rest/vibory/CAMPAIGN_VRN/tvd
- CAMPAIGN_VRN - ID kampanye
Contoh permintaan:
http://cikrf.ru/iservices/sgo-visual-rest/vibory/ 457422069597 / tvd
Hasil kueri
{
"_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 adalah nomor daerah. Angka nol biasanya bertanggung jawab atas hasil untuk satu distrik. Misalnya, jika pemilihan diadakan di bawah sistem campuran, "konstituensi nol" bertanggung jawab untuk memberikan suara di bawah sistem proporsional. Daerah pemilihan lainnya adalah anggota tunggal atau banyak anggota.
Seperti yang Anda lihat, struktur datanya juga berisi tautan yang dapat digunakan untuk mengetahui hasil pemilu. Tautan dibuat bahkan sebelum publikasi hasil pemungutan suara.
Daftar calon peserta kampanye pemilihan
http://cikrf.ru/iservices/sgo-visual-rest/vibory/CAMPAIGN_VRN/candidates/?page=PAGE_NUM&numokr=NUMTVD
- CAMPAIGN_VRN - ID kampanye
- PAGE_NUM - daftar nomor halaman
- NUMTVD - nomor daerah (opsional)
Contoh permintaan:
http://cikrf.ru/iservices/sgo-visual-rest/vibory/ 4674220125616 / kandidat /? Page = 1 & numokr = 11
Hasil kueri
{
"_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
}
}
Struktur halaman berisi jumlah halaman, ini dapat digunakan untuk menentukan kapan Anda mencapai halaman terakhir (atau dengan daftar kosong yang dikembalikan dari server).
API berisi metode lain, terutama untuk mengetahui informasi lebih lanjut tentang pemilu / kandidat. Jika perlu, Anda dapat dengan mudah melacak permintaan yang diperlukan. Sekarang, Anda dapat mulai mengupload data.
Mengunduh data dari situs web CEC
Sebelum melanjutkan dengan mengunduh data yang diperlukan, perlu menyusun daftar kampanye pemilu yang akan kami gunakan dalam proyek tersebut. Faktanya adalah bahwa “Smart Voting” tidak terjadi di mana-mana, tetapi dalam pemilu:
— ,
— ,
— ( 200 )
( 4 ).
//
Saya memutuskan untuk mengabaikan pemilihan sela untuk Duma Negara, karena tidak pentingnya data ini. Artikel Wikipedia tentang Election Day membantu menyusun daftar pemilihan untuk dewan lokal , karena hanya mencantumkan pemilihan di kota-kota besar.
Beralih ke seorang teman (yang membantu saya melaksanakan proyek ini dengan melakukan pekerjaan manual yang diperlukan), saya memintanya untuk menyusun daftar URL untuk masing-masing kampanye pemilu, mengambilnya dari halaman utama situs web CEC klasik . Faktanya adalah bahwa URL tersebut berisi pengenal wilayah dan kampanye yang akan kami perlukan untuk penguraian lebih lanjut.
vybory.izbirkom.ru/region/izbirkom?action=show&vrn=21120001136916&
region=11&prver=1&pronetvd=1
Hasilnya, daftar itu terdiri dari 43 kampanye pemilu. Secara total, lebih dari 9000 kampanye pemilihan terpisah diadakan pada Hari Pemilihan Tunggal ke badan-badan dari berbagai tingkatan.
Sekarang, dengan daftar pilihan dan metode API yang terdaftar sebelumnya di tangan, mudah untuk mengunduh data. Setelah menulis skrip python , membuat permintaan reguler menggunakan modul permintaan , saya menyimpan data tentang kandidat dan TPS dalam format JSON asli.
Hal utama yang perlu dipertimbangkan saat mengunduh informasi tentang TPS: tidak cukup hanya menelusuri semua kemungkinan nomor mulai dari 1 hingga server mengembalikan nilai kosong. Faktanya adalah bahwa penomoran PECs di wilayah tersebut dapat terputus, dan pergi, misalnya, dalam bentuk berikut:
... # 1001 - # 1016, # 1101 - # 1136, 1138 ...
atau:
# 0 - # 700, # 900 - # 1002, 1004 ...
Untuk menentukan nomor PEC maksimum di wilayah tersebut dan tidak membuat permintaan yang tidak perlu, saya mengumpulkan data sebagai berikut: Saya mencoba mengunggah data pada 1000 nomor pertama, dan kemudian memeriksa apakah saya + 1, i + 5, i + 100, i + 500, i + 1000 angka sesuai dengan PEC apa pun (dalam hal ini, terus mengunduh).
Juga, saya sarankan untuk menyimpan nomor PEC tempat Anda mengunduh data tentang kantor polisi. Faktanya, data yang dikembalikan tidak memuat nomor PEC, melainkan hanya berupa nama: "KPU No. 100" . Proses mendapatkan nomor PEC asli, yang kemudian harus saya tangani, menyebabkan bug dan frustrasi jangka pendek. Ternyata penomoran atas nama PECs di beberapa daerah memiliki format yang berbeda.
Misalnya, di Udmurtia, PEC memiliki penomoran berikut: "No. 1/01, No. 1/02, No. 1/3" , di wilayah Lipetsk: "No. 01-01, No. 01-02, No. 01-03" . Di wilayah Orenburg, saya menemukan sesuatu yang sangat eksotis: itu adalah satu-satunya wilayah di mana sejumlah komisi pemilihan dinamai menurut nama seseorang. Misalnya, "Komisi Pemilihan Umum No. 1696 dinamai menurut" Pustovitov Brothers "
Mendownload data dari situs "Smart Voting"
Sekarang, untuk setiap alamat PEC yang terkumpul, kami akan mengunduh data pemungutan suara dari situs web UMG. Sebelum itu, ada baiknya mempertimbangkan beberapa fitur (yang saya pelajari dalam proses):
Pertama, perlu diperhatikan bahwa alamat dalam database CEC memiliki format yang berbeda, terkadang bahkan di wilayah tertentu di wilayah tersebut. Saya harus menghapus singkatan "d.", "G." Dan "st.", Karena situs "Smart Voting" sama sekali tidak dapat menangani pencarian alamat untuk pertanyaan semacam itu. Saya juga merekomendasikan untuk menghapus kode pos dari alamat, serta awalan "Federasi Rusia" yang kadang-kadang ditemui.
Kedua, situs UMG memiliki perlindungan yang kuat terhadap serangan DDoS, dan bahkan jika Anda membuat ratusan permintaan dengan selang waktu 0,3 detik, IP Anda akan diblokir. Dimungkinkan untuk menggunakan sekumpulan proxy berbayar, tetapi secara pribadi saya hanya menggunakan proxy gratis dan permintaan bergantian dari IP saya sendiri dan pihak ketiga. Agar tidak diblokir, ada jeda sekitar 0,7 detik antar permintaan. Akibatnya, mengunduh semua data membutuhkan waktu sekitar satu hari.
Menggunakan kueri dari bab pertama, algoritme adalah sebagai berikut:
- Memformat alamat PEC
- Kami membuat permintaan untuk daftar alamat yang sesuai
- Kami mendapatkan daftar yang berisi ID halaman situs
- Kami memeriksa apakah kami telah mengunduh data tentang situs dengan pengenal ini
- Muat halaman HTML situs untuk pengenal ini
- Kami mengekstrak elemen "__NEXT_DATA__" dan menyimpan data dalam format JSON
Halaman ini diurai menggunakan pustaka beautifulsoup4 .
Proses ini bukannya tanpa cela: biasanya skrip tidak menemukan selusin TPS di suatu wilayah di situs web, atau di alamat salah satu PEC, Anda dapat menemukan informasi tentang PEC yang sama sekali berbeda.
Ini bukan masalah, karena untuk setiap distrik, kami hanya perlu menemukan setidaknya satu halaman yang sesuai di situs.
Untuk memvalidasi kelengkapan data, kami menulis skrip sederhana yang memeriksa apakah kumpulan data yang diunduh dari situs UMG berisi informasi tentang setiap daerah pemilihan. Jika ada yang hilang, kami mengisi dataset secara manual. Sekali lagi, ada kurang dari 10 situasi luar biasa seperti itu dari 1.100 distrik.
Menggabungkan data dari situs web UMG dan CEC
Pada tahap ini, kami mengumpulkan struktur data yang mudah dengan informasi tentang setiap kandidat menurut distrik: ID kandidat, nama lengkap, partai, tag dengan informasi tentang apakah dia didukung oleh UMG.
Contoh kumpulan data kandidat yang dikumpulkan
{
"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
}
],
...
}
Algoritme ini cukup mudah:
- Berdasarkan larik data dari website UMG, kami membuat daftar kandidat yang didukung untuk setiap kabupaten
- Dengan menggunakan data array dari situs CEC, kami membuat daftar kandidat yang diterima untuk setiap daerah pemilihan yang telah difilter
- Di tiap kabupaten, berdasarkan nama, kami menghitung korespondensi Calon-UMG-Calon-KTK
Tentu saja, algoritme sederhana seperti itu harus memperhitungkan banyak potensi situasi masalah.
Pertama, ada kemungkinan di satu daerah pemilihan akan ada calon dengan nama yang sama persis. Untungnya, di antara 5.000 calon, keadaan seperti itu hanya terjadi pada satu kasus, dan tidak ada calon yang didukung oleh UMG.
Kedua, harus diperhatikan bahwa mungkin terdapat kesalahan dalam database situs CEC. Kesalahan paling umum: jeda baris dan spasi ekstra di nama lengkap. Selain itu, pada saat pendataan hasil pemungutan suara, terdapat situasi dimana huruf "" pada nama belakang diganti dengan "e".
Ketiga, relevansi data harus diperhitungkan. Data di situs CEC dan UMG berubah dan diperbarui hingga hari Sabtu: beberapa calon dicopot / dipekerjakan kembali, di beberapa kabupaten dukungan UMG berubah.
Untuk memvalidasi daftar UMG, skrip sederhana telah ditulis yang membuat satu permintaan per distrik (bagaimanapun, kumpulan data yang telah kami kumpulkan sekarang memungkinkan kami untuk secara unik mengidentifikasi halaman yang didedikasikan untuk setiap distrik) dan memeriksa apakah namanya cocok dengan yang kami terima sebelumnya.
Tugas yang menarik adalah identifikasi partai berdasarkan nama cabangnya. Poin ini dapat dilewati, tetapi saya memutuskan untuk melakukannya untuk menyatukan informasi. Masalahnya, calon dari satu partai mungkin memiliki nama yang berbeda di database CEC. Misalnya, dalam kasus KPRF, terdapat lebih dari 40 opsi:
() " "
- ""
" "
...
Situasi tersebut berubah menjadi masalah penguraian yang menarik, ketika ada 25 batch dan hampir masing-masing memiliki ejaan yang berbeda untuk setiap wilayah. Untungnya, dengan bantuan teman saya, yang membantu saya dengan semua pekerjaan manual, kami menyusun daftar kata kunci yang digunakan oleh partai kandidat secara unik.
Mengupload hasil pemilu dari situs CEC
Kumpulan data yang terkumpul cukup untuk mencapai tujuan awal proyek - kami menyusun daftar kandidat UMG-2020 untuk setiap daerah pemilihan. Namun jika ada peluang teknis untuk mendapatkan hasil pemilu, mengapa tidak dimanfaatkan?
Hasil pemilihan distrik
http://cikrf.ru/iservices/sgo-visual-rest/vibory/CAMPAIGN_VRN/results/DISTRICT_VRN/major
- CAMPAIGN_VRN - ID kampanye
- DISTRICT_VRN - ID Distrik
Contoh permintaan:
http://cikrf.ru/iservices/sgo-visual-rest/vibory/ 457422069597 / results / 457422069602 / major
Hasil kueri
{
"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"
}
}
Seperti yang Anda lihat, hasilnya dikembalikan dalam bentuk protokol komisi regional. Setiap wilayah berbeda dalam format protokol dan jumlah baris pengantar di dalamnya, jadi validasi yang cermat atas data yang Anda ekstrak harus dilakukan.
Ketika GAS "Vybory" mulai mempublikasikan hasil awal, saya mengalami sedikit kekecewaan. Ternyata melalui API Anda hanya bisa mendapatkan data tentang hasil yang disetujui secara resmi. Hasil sementara masih bisa dilihat di situs lama KPU, tapi tidak melalui layanan web baru.
Sehari kemudian, sudah diketahui hasil 50%, dan menjelang akhir minggu hampir semua hasil pemilu dijumlahkan, beberapa daerah masih menolak untuk menyetujui hasil tersebut. Saat tulisan ini dibuat, sudah 7 hari berlalu, dan hasil pemilu di Tambov belum juga disetujui. Selain itu, di beberapa daerah pemilihan ada penghitungan ulang, itulah sebabnya hasil ini juga tidak tersedia melalui API.
Kesimpulan: Metode API saat ini tidak cocok untuk menerima hasil pemungutan suara dengan segera. Anda harus menunggu lebih dari seminggu sampai hasil disetujui, atau Anda harus mengurai situs lama komisi pemilihan, mencari cara untuk melewati captcha.
Saya lelah menunggu pemilihan disetujui di ~ 30 dari 1100 daerah pemilihan, jadi saya menulis skrip menggunakan perpustakaan selenium yang mengunduh data dari situs klasik komisi pemilihan dan meminta saya untuk menyelesaikan captcha secara manual untuk setiap permintaan. Dengan jumlah permintaan yang sedikit, tidak butuh waktu lama untuk menyelesaikan captcha secara manual.
Alhasil, saya mengumpulkan data hasil pemungutan suara ke dalam struktur berikut :
Contoh hasil pemungutan suara daerah
{
...
"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
},
...
}
Untuk setiap daerah pemilihan, saya menyimpan jumlah total pemilih di daftar (untuk menghitung jumlah pemilih), jumlah surat suara yang sah dan tidak sah. Struktur kamus berisi: Pengenal kandidat -> Jumlah suara yang diketiknya.
Publikasi hasil UMG-2020
Pertama, saya menerbitkan data yang dikumpulkan dalam format JSON di GitHub . Data akan diperbarui hingga hasilnya divalidasi di semua kabupaten.
Kedua, untuk menarik perhatian pada proyek, saya memutuskan untuk membuat Google Spreadsheet, yang berisi semua data yang dikumpulkan dalam bentuk yang mudah untuk analisis visual.
Saya tidak akan menjelaskan secara detail, tidak ada kesulitan (kecuali untuk mempelajari Google Sheets API) yang muncul. Saya merekomendasikan artikel ini , yang detailnya berinteraksi dengan Google Sheets API dengan Python.
Hasilnya, kami mendapat tabel berikut, yang berisi:
- Daftar pemilihan yang terlibat
- Daftar pihak yang terlibat
- Daftar kandidat berdasarkan distrik
- Hasil Pemilu Menurut Distrik
- Data ringkasan kering
Kata Penutup
Ide proyek mini ini muncul 3 hari sebelum hari pemungutan suara, dan saya secara pribadi senang dengan bagaimana saya berhasil mempelajari dan menerapkan semuanya dalam waktu sesingkat mungkin (meskipun kodenya ternyata mengerikan).
Saya tidak akan menarik kesimpulan apa pun tentang hasil dari strategi Smart Voting, saya hanya menyediakan alat untuk penggemar statistik pemilu. Saya yakin akan ada beberapa di antara Anda dan segera kita akan melihat studi yang luar biasa, dengan grafik dan diagram yang menarik.