見出し画像

電験三種の過去問をPythonで取得する方法


注意事項

Pythonを用いて、電気技術者試験センター(以下、試験センター)の過去問掲載ページにある過去問を一括取得する方法を解説する。勉強用に取得するのは、問題ないが、過去問を勉強以外に使用する際は、試験センターのHPで過去問の使用について確認、もしくは試験センターへ問い合わせを行ってほしい。
試験センターQ&A
https://www.shiken.or.jp/qa.html

必要な外部ライブラリ

今回は外部ライブラリとしてBeautifulsoup4というライブラリを使用する。そのため、インストールしていない場合は、以下のコマンドでインストールする必要がる。

pip用

pip install beautifulsoup4

Anaconda用

conda install beautifulsoup4

プログラム

必要ライブラリのimport

Beautifulsoup4以外は標準ライブラリなので、インストールしなくても使用できる。

from bs4 import BeautifulSoup
import urllib.request as req
import urllib
import os
import time
from urllib.parse import urljoin
import datetime

関数定義

ファイル名で下期、上期をつけるための関数定義。ファイル名を自身で変更する場合は、不要である。

def make_filenamelist(file_list, year, half_str):
    file_list.append(f'理論{year}_{half_str}.pdf')
    file_list.append(f'電力{year}_{half_str}.pdf')
    file_list.append(f'機械{year}_{half_str}.pdf')
    file_list.append(f'法規{year}_{half_str}.pdf')
    file_list.append(f'解答{year}_{half_str}.pdf')
    return file_list

aタグを取得

urlに電験三種の過去問掲載ページのurlを指定する。

url = "https://www.shiken.or.jp/answer/index_list.php?exam_type=30"
res = req.urlopen(url)
soup = BeautifulSoup(res, "html.parser")
result = soup.select("a[href]")

リンクのみ取得

link_list =[]
for link in result:
    href = link.get("href")
    link_list.append(href)

PDFのみ取得

電験の場合は、ファイルの拡張子がPDFとpdfがある。

pdf_list = [temp for temp in link_list if temp.endswith(('pdf', 'PDF'))]

試験問題の取得

# 過去問ファイル名
pdf_str = ['T1-R', 'T1-D', 'T1-K', 'T1-H', 'T1-%EF%BC%A8', 'T1%28R%29', 'T1%28D%29', 'T1%28K%29', 'T1%28H%29', \
           'T2-R', 'T2-D','T2-K', 'T2-H']
for y in range(2009,2012):
    pdf_str.append(f'TR_{y}')
    pdf_str.append(f'TD_{y}')
    pdf_str.append(f'TK_{y}')
    pdf_str.append(f'TH_{y}')
# 解答
for y in range(2009,2024):
    if y >= 2022:
        pdf_str.append(f'{y}_3_1')
        pdf_str.append(f'{y}_3_2')
    else:
        pdf_str.append(f'{y}_3')

test_pdf_list = [temp for temp in pdf_list if os.path.splitext(os.path.basename(temp))[0] in pdf_str]

相対URLを絶対URLにする

abs_pdf_list = []
for relative in test_pdf_list:
    temp_url = urljoin(url, relative)
    abs_pdf_list.append(temp_url)

保存用のファイル名を決める

# 保存用のファイル名
filename_list1 = []
dt_now = datetime.datetime.now()
for y in range(dt_now.year,2022,-1):
    if dt_now.month <= 4:
        filename_list1 = make_filenamelist(filename_list1, y, "下期")
    else:
        filename_list1 = make_filenamelist(filename_list1, y, "上期")
        filename_list1 = make_filenamelist(filename_list1, y, "下期")
filename_list2 = []
for y in range(2022,2008,-1):
    if y == 2022:
        filename_list2 = make_filenamelist(filename_list2, y, "上期")
    else:
        filename_list2.append(f'理論{y}.pdf')
        filename_list2.append(f'電力{y}.pdf')
        filename_list2.append(f'機械{y}.pdf')
        filename_list2.append(f'法規{y}.pdf')
        filename_list2.append(f'解答{y}.pdf')

保存用のディレクトリ作成

target_dir = "ここに保存先の絶対パスを指定する"
savepath_list = []
for filename in filename_list:
    savepath_list.append(os.path.join(target_dir, filename))

ダウンロードの実施

ダウンロード先のサイトに負荷を掛けないように、1回あたり2秒間の間隔をあける。

for (pdflink, savepath) in zip(abs_pdf_list, savepath_list):
    urllib.request.urlretrieve(pdflink, savepath)
    time.sleep(2)

コード全体

保存先のディレクトリを設定するのを、忘れないようにご注意ください。

from bs4 import BeautifulSoup
import urllib.request as req
import urllib
import os
import time
from urllib.parse import urljoin
import datetime


def make_filenamelist(file_list, year, half_str):
    file_list.append(f'理論{year}_{half_str}.pdf')
    file_list.append(f'電力{year}_{half_str}.pdf')
    file_list.append(f'機械{year}_{half_str}.pdf')
    file_list.append(f'法規{year}_{half_str}.pdf')
    file_list.append(f'解答{year}_{half_str}.pdf')
    return file_list


# <a>タグを取得
url = "https://www.shiken.or.jp/answer/index_list.php?exam_type=30"
res = req.urlopen(url)
soup = BeautifulSoup(res, "html.parser")
result = soup.select("a[href]")


# リンクのみ取得
link_list =[]
for link in result:
    href = link.get("href")
    link_list.append(href)


# pdfのみ取得
pdf_list = [temp for temp in link_list if temp.endswith(('pdf', 'PDF'))]

# 過去問ファイル名
pdf_str = ['T1-R', 'T1-D', 'T1-K', 'T1-H', 'T1-%EF%BC%A8', 'T1%28R%29', 'T1%28D%29', 'T1%28K%29', 'T1%28H%29', \
           'T2-R', 'T2-D','T2-K', 'T2-H']
for y in range(2009,2012):
    pdf_str.append(f'TR_{y}')
    pdf_str.append(f'TD_{y}')
    pdf_str.append(f'TK_{y}')
    pdf_str.append(f'TH_{y}')
# 解答
for y in range(2009,2024):
    if y >= 2022:
        pdf_str.append(f'{y}_3_1')
        pdf_str.append(f'{y}_3_2')
    else:
        pdf_str.append(f'{y}_3')

test_pdf_list = [temp for temp in pdf_list if os.path.splitext(os.path.basename(temp))[0] in pdf_str]


# 相対URLを絶対URLにする
abs_pdf_list = []
for relative in test_pdf_list:
    temp_url = urljoin(url, relative)
    abs_pdf_list.append(temp_url)
    

# 保存用のファイル名
filename_list1 = []
dt_now = datetime.datetime.now()
for y in range(dt_now.year,2022,-1):
    if dt_now.month <= 4:
        filename_list1 = make_filenamelist(filename_list1, y, "下期")
    else:
        filename_list1 = make_filenamelist(filename_list1, y, "上期")
        filename_list1 = make_filenamelist(filename_list1, y, "下期")
filename_list2 = []
for y in range(2022,2008,-1):
    if y == 2022:
        filename_list2 = make_filenamelist(filename_list2, y, "上期")
    else:
        filename_list2.append(f'理論{y}.pdf')
        filename_list2.append(f'電力{y}.pdf')
        filename_list2.append(f'機械{y}.pdf')
        filename_list2.append(f'法規{y}.pdf')
        filename_list2.append(f'解答{y}.pdf')

filename_list = filename_list1 + filename_list2

# 保存用のディレクトリ作成
target_dir = "ここに保存先の絶対パスを指定する"
savepath_list = []
for filename in filename_list:
    savepath_list.append(os.path.join(target_dir, filename))


# ダウンロード
for (pdflink, savepath) in zip(abs_pdf_list, savepath_list):
    urllib.request.urlretrieve(pdflink, savepath)
    time.sleep(2)

参考にした記事

https://degitalization.hatenablog.jp/entry/2020/08/02/193536

関連記事

電験一種の過去問をPythonで取得する方法
https://note.com/elemag/n/n9f86c492dcc9?sub_rt=share_pw

電験二種の過去問をPythonで取得する方法
https://note.com/elemag/n/ne296a22a871f?sub_rt=share_pw

サイト

https://sites.google.com/view/elemagscience/%E3%83%9B%E3%83%BC%E3%83%A0


この記事が気に入ったらサポートをしてみませんか?