Seleniumを用いてトルコ投票データベースを作る方法

出版日: 2024年5月1日

Seleniumを用いてトルコ投票データベースを作る方法

皆さんは2024年3月31日にトルコで地方選挙が行われたことをご存知の方もいるかもしれません。これらの選挙は、22年間続いたAKP政権が選挙で初めて敗北したことで世界中に波紋を広げました。 選挙の驚くべき勝者はCHPであり、彼らは現在、国の60%を占める都市と国の80%を占める都市を統治しています。

では、これはどのようにして起こったのでしょうか?

背景

トルコのテレビを見ていると、評論家たちは国の経済的理由による不満を感じている退職者のせいでこの敗北を非難しています。

トルコでは、若者の70%以上がCHPの政策を支持しており、一方でAKPは若者の支持を得られていないという一般的な認識があります。したがって、CHPの支持は今後さらに高まると言われています。

評論家は誤った予測をすることが知られており、誤った情報を提供することがあります。データサイエンティストとして、私はこれらの主張が本当かどうかをデータを使用してチェックすることが喜びであり、義務です。

データ

このような分析を行うためには、有権者の年齢構成と投票方法が必要です。通常、この目的のためには費用のかかる調査が行われます。 しかし、私たちが使用できる素晴らしい公に利用可能なデータがあります。

トルコ統計研究所

トルコ統計研究所(TUIK)は選挙結果データおよび投票者の年齢/性別/教育構成を地区レベルで公開しています。トルコの81の州は973の地区に分かれています。

私たちの目的のためには、年齢データだけを見れば十分であり、若者は約30歳以下の有権者として、退職者はトルコの定年年齢が65歳であるため、65歳以上の人々として表すことができます。

私たちは、TUIKの選挙データベースを見ることでこのデータを取得できます。残念ながら、最新の利用可能なデータは2018年のデータベースです。2018年以降、多くのことが変わりましたが、このデータは大きな有権者のトレンドを垣間見ることができます。

選挙

このデータベースの問題は、各地区の個別のレポートを作成する必要があることです。地区レベルのレポートは以下のようになります:

選挙結果

トルコには973の地区がありますので、これは退屈で疲れる作業です。ここでスクレイピングが登場します。

データのスクレイピング

トルコには973の地区がありますので、これは退屈で疲れる作業です。ここでスクレイピングが登場します。

このGitHubリポジトリで、データをスクレイプし、データフレームにまとめ、結果のCSVファイルを生成するために必要なすべてのコードを確認してください。

全体的なアイデアは、セレンを使用して市と地区を切り替え、"レポートをダウンロード"をクリックすることにより、すべての地区をループし、次の地区に移動することです。都市のすべての地区が消耗されると、次の都市に移動します。この方法で、トルコの81の都市と937の地区をループし、各地区についてのレポートをダウンロードします。

from selenium import webdriver
import chromedriver_autoinstaller
from selenium.webdriver.common.by import By
import time
chromedriver_autoinstaller.install()

###### WebDriverを開始
driver = webdriver.Chrome()
time.sleep(1)

###### メインサイトに移動
driver.get("https://biruni.tuik.gov.tr/secimdagitimapp/secimsecmen.zul")
time.sleep(1)

###### 希望の地域のラジオボタンを選択
for span in driver.find_elements(By.CSS_SELECTOR, ".grid-od span"):
    if span.text == "2018":
        span.find_element(By.CSS_SELECTOR, "input").click()
        time.sleep(1)


for span in driver.find_elements(By.CSS_SELECTOR, ".grid-od span"):
    if span.text == "Yurt içi seçmen":
        span.find_element(By.CSS_SELECTOR, "input").click()
        time.sleep(1)

for span in driver.find_elements(By.CSS_SELECTOR, ".grid-od span"):
    if span.text == "Yaş grubu":
        span.find_element(By.CSS_SELECTOR, "input").click()
        time.sleep(1)

for span in driver.find_elements(By.CSS_SELECTOR, ".grid .gc span"):
    if span.text == "İBBS-Düzey4 (İlçe)":
        span.find_element(By.CSS_SELECTOR, "input").click()
        time.sleep(1)

###### 市の中の都市を識別します(全部で81個あるはず)
tables = driver.find_elements(By.CSS_SELECTOR, ".listbox-btable")

for table in tables:
    if "Adana" in table.text:
        cities = table.find_elements(By.CSS_SELECTOR, "td")
        break

city_names = [city.text for city in cities]

###### 地区ごとにデータを保存します
for city in cities:
    city.click()
    time.sleep(2)

    tables = driver.find_elements(By.CSS_SELECTOR, ".listbox-btable")

    for table in tables:
        if "Tüm İlçeler" in table.text:
            districts = table.find_elements(By.CSS_SELECTOR, "td")
            break

    district_names = [district.text for district in districts]
    districts = [district for district in districts if "Tüm İlçeler" not in district.text]
    
    for district in districts:
        district.click()
        time.sleep(1)
    
        # Excelを設定します
        excel =  driver.find_element(By.CSS_SELECTOR, 'span[title="EXCEL"]').find_element(By.CSS_SELECTOR, 'input').click()
        time.sleep(1)
        
        ## データを保存します
        save =  driver.find_element(By.CSS_SELECTOR, 'input[value="Raporu Oluştur"]').click()
        
        ## ログ、スリープ
        print(city.text, district.text)
        time.sleep(1)

データの集計

データを収集したら、937のHTMLファイルが処理待ちです。以下のコードを使用して、データをクリーンアップして統合し、1つの大きなCSVファイルに集約します:

import pandas as pd
import os
from bs4 import BeautifulSoup
import warnings
warnings.simplefilter(action='ignore')

folder = "<TUIKからダウンロードしたファイルのアドレス>"

paths = [f for f in os.listdir(folder) if f.endswith("xls")]
dfs = []

for path in paths:
    with open(f"{folder}/{path}", "r", encoding="iso-8859-9") as f:
        text = f.read()
        soup = BeautifulSoup(text, "html")
        tables = pd.read_html(str(soup.findAll("table")[1]))
        city = tables[0].iloc[0, 0]
        df = tables[2]
        df.drop(1, axis=1, inplace=True)
        district = df.iloc[0, 0]
        df.columns = ["age", "male", "female", "all"]
        df["city"] = city
        df["district"] = district
        df = df[1:]
        for col in df.columns:
            df[col] = df[col].str.replace(".", "", regex=False)
        df = df[df["age"] != "Toplam"]
        df["male"] = pd.to_numeric(df["male"])
        df["female"] = pd.to_numeric(df["female"])
        df["all"] = pd.to_numeric(df["all"])

        dfs.append(df)
        
df = pd.concat(dfs, axis=0, ignore_index=True)
df.to_csv("data.csv", index=False)

結果

結果ファイルは以下のようになります。これは、トルコの2018年の総選挙における地区レベルの有権者の年齢データを示しています: データスクレイピングの結果

結論

このデータを使用すると、回帰などのモデルを実行して、有権者の年齢構成が投票結果にどのように影響しているかを確認できます。各地区はデータポイントとして扱われ、937のデータポイントで統計的に有意な結果を得ることができるはずです。しかし、これは別の記事のためのものです。

このデータが多くの人々によってトルコの選挙の有用なモデルを開発するために使用されることを願っています。

コードとデータはGitHubリポジトリでご確認ください。

Happy hacking!

このブログは英語からChatGPTによって翻訳されました。不明な点がある場合は、お問い合わせページからご連絡ください。

コメントを残す

コメント

その他のブログ

SvelteとJavaScriptを使用してシンプルで動的なツールチップを作成する

2024/06/19

SvelteとJavaScriptを使用してシンプルで動的なツールチップを作成する

JavaScriptSvelteTooltip動的シンプルツールチップフロントエンド
JavaScriptを用いて東京都のインタラクティブな地図を作成する

2024/06/17

JavaScriptを用いて東京都のインタラクティブな地図を作成する

SvelteSVGJavaScriptTailwindインタラクティブな地図東京市区町村23区地図
Matplotlibで日本語文字化けを解決できる簡単な方法

2024/06/14

Matplotlibで日本語文字化けを解決できる簡単な方法

MatplotlibグラフチャートPython日本語文字化け問題バグ
書評 | トーキング・トゥ・ストレンジャーズ 「よく知らない人」について私たちが知っておくべきこと by マルコム・グラッドウェル

2024/06/13

書評 | トーキング・トゥ・ストレンジャーズ 「よく知らない人」について私たちが知っておくべきこと by マルコム・グラッドウェル

書評トーキング・トゥ・ストレンジャーズ「よく知らない人」について私たちが知っておくべきことマルコム・グラッドウェル
日本語で最もよく使われる3000字の漢字

2024/06/07

日本語で最もよく使われる3000字の漢字

3000よく使う準漢字使用回数漢字日本語漢字リスト漢字普及率日本語能力試験独学勉強単語
VSCodeでRegexを使用してReplaceする方法

2024/06/07

VSCodeでRegexを使用してReplaceする方法

VSCodeRegex検索置き換える条件付き置換FindReplaceConditional Replace
SvelteではReadable Storeを使用するな

2024/06/06

SvelteではReadable Storeを使用するな

SvelteReadableWritableステート管理ストアStore速度メモリファイルサイズ
GzipとPakoでデータを圧縮してWebサイトのローディング速度を上げる方法

2024/06/05

GzipとPakoでデータを圧縮してWebサイトのローディング速度を上げる方法

Gzip圧縮PakoWebサイトローディング速度SvelteKit
JavaScriptを使用してWebページ上でマウスが指している単語を特定する

2024/05/31

JavaScriptを使用してWebページ上でマウスが指している単語を特定する

JavascriptマウスPointerHoverWeb開発
SvelteとSVGを用いてインタラクティブな地図を作成する

2024/05/29

SvelteとSVGを用いてインタラクティブな地図を作成する

SvelteSVGインタラクティブな地図フロントエンド
書評 | Originals 誰もが「人と違うこと」ができる時代 by アダム・グラント & シェリル・サンドバーグ

2024/05/28

書評 | Originals 誰もが「人と違うこと」ができる時代 by アダム・グラント & シェリル・サンドバーグ

書評Originals誰もが「人と違うこと」ができる時代アダム・グラント & シェリル・サンドバーグ
Javascriptを使用して数独を解く方法

2024/05/27

Javascriptを使用して数独を解く方法

数独を解くアルゴリズムJavaScriptコーディング
ウェブサイトへのトラフィックを1か月で10倍に増やした方法

2024/05/26

ウェブサイトへのトラフィックを1か月で10倍に増やした方法

ウェブサイトへのトラフィック増加クリックインプレッションGoogle Search Console
人生はサイクリングに似ている

2024/05/24

人生はサイクリングに似ている

サイクリング人生哲学成功
JavaScriptでバックトラッキング・アルゴリズムを用いて完全な数独グリッドを生成する

2024/05/19

JavaScriptでバックトラッキング・アルゴリズムを用いて完全な数独グリッドを生成する

数独バックトラッキング・アルゴリズム完全なグリッドJavaScript
Tailwindが素晴らしい理由とWeb開発をいかに楽にするか

2024/05/16

Tailwindが素晴らしい理由とWeb開発をいかに楽にするか

Tailwind素晴らしいフロントエンドWeb開発
PythonとGitフックを使用してサイトマップを自動的に生成する

2024/05/15

PythonとGitフックを使用してサイトマップを自動的に生成する

GitフックPythonサイトマップSvelteKit
書評 | Range (レンジ) 知識の「幅」が最強の武器になる by デイビッド・エプスタイン

2024/05/14

書評 | Range (レンジ) 知識の「幅」が最強の武器になる by デイビッド・エプスタイン

書評Range (レンジ)David Epstein (デイビッド・エプスタイン)知識の「幅」が最強の武器になる
SvelteとSvelteKitはなんですか?

2024/05/13

SvelteとSvelteKitはなんですか?

SvelteSvelteKitFront-endVite
SvelteKitで国際化(多言語化)

2024/05/12

SvelteKitで国際化(多言語化)

国際化多言語SvelteKitI18N
SvelteでCachingを用いてDeploy時間を短縮する方法

2024/05/11

SvelteでCachingを用いてDeploy時間を短縮する方法

SvelteEnhanced ImageCachingDeploy Time
SvelteとIntersection Oberverによるレイジーローディング

2024/05/10

SvelteとIntersection Oberverによるレイジーローディング

レイジーローディングウェブサイト速度の最適化SvelteIntersection Observer
遺伝的アルゴリズムで最適な株式ポートフォリオを作る方法

2024/05/10

遺伝的アルゴリズムで最適な株式ポートフォリオを作る方法

株式書状ポートフォリ最適化遺伝的アルゴリズムPython
Pythonを用いてShapeFileをSVGに変換できる方法

2024/05/09

Pythonを用いてShapeFileをSVGに変換できる方法

ShapeFileSVGPythonGeoJSON
Svelteの反応性:変数、バインディング、およびキー関数

2024/05/08

Svelteの反応性:変数、バインディング、およびキー関数

Svelte反応性バインディングキー関数
書評 | 孫子の兵法

2024/05/07

書評 | 孫子の兵法

書評The Art Of War (兵法)Sun Tzu (孫子)Thomas Cleary
スペシャリストは終了。ゼネラリスト万歳!

2024/05/06

スペシャリストは終了。ゼネラリスト万歳!

専門家ジェネラリストパラダイムシフトソフトウエア・エンジニアリング
トルコ人の有権者の投票行動をPythonでの分析

2024/05/03

トルコ人の有権者の投票行動をPythonでの分析

トルコ投票者年齢分析国家投票有権者行動分析
SvelteとTailwindを使用してInfinite Scrollできる方法

2024/04/30

SvelteとTailwindを使用してInfinite Scrollできる方法

SvelteTailwindInfinite ScrollFront-end
1年間以内で日本語を駆使できるようになるための方法

2024/04/29

1年間以内で日本語を駆使できるようになるための方法

日本語短時間言語学習日本語能力試験ビジネス日本語
SvelteとTailwindを用いたWebサイトテンプレート

2024/04/25

SvelteとTailwindを用いたWebサイトテンプレート

Web開発フロントエンドSvelteTailwind
怠惰なエンジニアとひどいデザイン

2024/01/29

怠惰なエンジニアとひどいデザイン

怠け者エンジニア質の悪い製品StarbucksSBI証券
偉大さについて

2024/01/28

偉大さについて

雄大さ人生の意味満足できる人生目的
MacBook で PDF を PNG に変換する

2024/01/28

MacBook で PDF を PNG に変換する

PDFPNGMacBookAutomator
2023年振り返り:24冊の読んだ本のまとめ

2023/12/31

2023年振り返り:24冊の読んだ本のまとめ

読書 2023振り返り
Python PILを使用して写真コラージュを作成する方法

2023/12/30

Python PILを使用して写真コラージュを作成する方法

PythonPIL画像処理コラージュ
ウェブサイトの訪問者のデバイスとブラウザを検出する方法

2024/01/09

ウェブサイトの訪問者のデバイスとブラウザを検出する方法

Javascript端末検知ブラウザ検知Website分析
ChatGPT回答の解析

2024/01/19

ChatGPT回答の解析

ChatGPT大規模言語モデル機械学習生成AI