ハローワークの求人情報をスクレイピング(Python + Selenium + BeautifulSoup)
この記事は、以下のハローワークインターネットサービスから求人情報を自動で取得する試みを記録したものです: www.hellowork.mhlw.go.jp
まずは、ソースコードと実行結果をお見せし、後ほどこの記事を書いた経緯などを話します。
ソースコード:HelloWork_Scraping_ST.py
from selenium import webdriver from selenium.webdriver.support.ui import Select import time from bs4 import BeautifulSoup import re # ハローワークインターネットサービスのURL url = "https://www.hellowork.mhlw.go.jp/" # 以下からご自分で使用しているChromeのバージョンに合ったChromeDriverをダウンロードして下さい # https://chromedriver.chromium.org/downloads # ChromeDriverをご自分のPCの任意の場所に保存して、以下のDRIVER_PATHに設定して下さい。 DRIVER_PATH = 'D:\source\py\ChromeWebDriver\chromedriver_win32\chromedriver.exe' driver = webdriver.Chrome(executable_path=DRIVER_PATH) driver.get(url) time.sleep(1) # 「求人情報検索」をクリック driver.find_element_by_class_name("retrieval_icn").click() time.sleep(1) # 福岡県内で探す element = driver.find_element_by_id("ID_tDFK1CmbBox") Select(element).select_by_value("40") #福岡 time.sleep(1) # 「市区町村」を選ぶために「選択」をクリック buttons = driver.find_elements_by_css_selector("input.button"); buttons[1].click() time.sleep(1) # 市区町村名のドロップダウンリストを選択 element = driver.find_element_by_id("ID_rank1CodeMulti") # 【東日本】市区町村名コード(5桁・6桁)一覧(更新:2019.9.15) # http://www13.plala.or.jp/bigdata/municipal_code_1.html # 【西日本】市区町村名コード(5桁・6桁)一覧(更新:2019.9.15) # http://www13.plala.or.jp/bigdata/municipal_code_2.html # 市区町村名コードを基に、5つまで市区町村名を選択 Select(element).select_by_value("40131") #東区 Select(element).select_by_value("40132") #博多区 Select(element).select_by_value("40133") #中央区 Select(element).select_by_value("40134") #南区 Select(element).select_by_value("40135") #西区 time.sleep(1) # OKをクリック driver.find_element_by_id("ID_ok").click() time.sleep(1) # 佐賀県内で探す element = driver.find_element_by_id("ID_tDFK2CmbBox") Select(element).select_by_value("41") #佐賀 time.sleep(1) # 「市区町村」を選ぶために「選択」をクリック buttons = driver.find_elements_by_css_selector("input.button"); buttons[2].click() time.sleep(1) # 市区町村名のドロップダウンリストを選択 element = driver.find_element_by_id("ID_rank1CodeMulti") # 市区町村名コードを基に、5つまで市区町村名を選択 Select(element).select_by_value("41201") #佐賀市 Select(element).select_by_value("41203") #鳥栖市 time.sleep(1) # OKをクリック driver.find_element_by_id("ID_ok").click() time.sleep(1) # 長崎県内で探す element = driver.find_element_by_id("ID_tDFK3CmbBox") Select(element).select_by_value("42") #長崎 time.sleep(1) # 「市区町村」を選ぶために「選択」をクリック buttons = driver.find_elements_by_css_selector("input.button"); buttons[3].click() time.sleep(1) # 市区町村名のドロップダウンリストを選択 element = driver.find_element_by_id("ID_rank1CodeMulti") # 市区町村名コードを基に、5つまで市区町村名を選択 Select(element).select_by_value("42202") #佐世保市 Select(element).select_by_value("42204") #諫早市 Select(element).select_by_value("42205") #大村市 time.sleep(1) # 「OK」をクリック driver.find_element_by_id("ID_ok").click() time.sleep(1) # 「職業分類を選択」をクリック buttons = driver.find_elements_by_css_selector("input.button"); buttons[7].click() time.sleep(1) # 「職業分類」のドロップダウンリストを選択 element = driver.find_element_by_id("ID_rank00Code") # 「B 専門的・技術的職業」を選択 Select(element).select_by_value("B") # 「下位」をクリック driver.find_element_by_id("ID_down").click() time.sleep(1) # 「下位」のドロップダウンリストを選択 element = driver.find_element_by_id("ID_rank00Code") # 「10 情報処理・通信技術者」を選択 Select(element).select_by_value("10") # 「下位」をクリック driver.find_element_by_id("ID_down").click() time.sleep(1) # 「下位」のドロップダウンリストを選択 element = driver.find_element_by_id("ID_rank00Code") # 「104 ソフトウェア開発技術者」を選択 Select(element).select_by_value("104") # 「下位」をクリック driver.find_element_by_id("ID_down").click() time.sleep(1) # 「10401 ソフトウェア開発技術者(WEB・オープン系)」が既に選択されているので、「決定」をクリック driver.find_element_by_id("ID_ok").click() time.sleep(1) # 「フリーワード」の「OR検索」ラジオボタンをクリック driver.find_element_by_id("ID_freeWordRadioBtn0").click() time.sleep(1) # 「フリーワード」の入力欄をクリック element = driver.find_element_by_id("ID_freeWordInput") # 「フリーワード」の入力欄に"Python C#"と入力(注意:全角文字で入力すること!) element.send_keys("Python C#") time.sleep(1) # 「詳細検索条件」をクリック driver.find_element_by_id("ID_searchShosaiBtn").click() time.sleep(1) # 「交代制(シフト制)を含まない」にチェック driver.find_element_by_id("ID_LkiboShgJnCKBox1").click() time.sleep(1) # 「裁量労働制を含まない」にチェック driver.find_element_by_id("ID_LkiboShgJnCKBox2").click() time.sleep(1) # 「変形労働時間制を含まない」にチェック driver.find_element_by_id("ID_LkiboShgJnCKBox3").click() time.sleep(1) # 「派遣・請負を含まない」にチェック driver.find_element_by_id("ID_hakenUkeoinCKBox3").click() time.sleep(1) # 「転勤の可能性なし」にチェック driver.find_element_by_id("ID_LsonotaCKBox4").click() time.sleep(1) # print(driver.page_source) # 「OK」をクリック driver.find_element_by_id("ID_saveCondBtn").click() time.sleep(1) # 「検索」をクリック driver.find_element_by_id("ID_searchBtn").click() time.sleep(1) # 「表示件数」ドロップダウンリストをクリック element = driver.find_element_by_id("ID_fwListNaviDispBtm") # 「50件」を選択 Select(element).select_by_value("50") time.sleep(1) # 今見ているページをBeautifulSoupで解析 soup = BeautifulSoup(driver.page_source, "html.parser") # 「求人」のテーブルを検索 jobs = soup.find_all("table", attrs={"class": "kyujin"}) # 検索結果を格納する"message"を初期化 message = "" # 「職種」「月給」「勤務地」「仕事の内容」を取得する for i, job in enumerate(jobs): job_name = str(job.find("td", attrs={"class": "m13"}).text.strip()) salary_tags = job.find_all("tr",attrs={"class": "border_new"})[5].select(".disp_inline_block") for t, salary_tag in enumerate(salary_tags): job_salary = salary_tag.text # 月給の上限の金額を正規表現で抽出 m = re.search('(〜)(\d{3}),(\d{3})', job_salary) highest = int(m.group(2) + m.group(3)) # 月給の上限の金額が40万円以上だった場合にのみ、"message"に格納する if highest >= 400000: print("〇 ", highest) job_description = job.find(string='仕事の内容').parent.find_next_sibling().text.replace('\n', '') job_location = job.find(string='就業場所').parent.find_next_sibling().text.replace('\n', '') message = message + "■{0} ( {1} ){2} \n□{3}\n".format(job_name, job_salary, job_location, job_description) else: print("× ", highest) # 検索結果の出力 print(message) # 「次へ」をクリックして、次ページを表示する # TODO: 「次へ」がクリックできる限り、以下の表示をループで回す、多分簡単 # TODO: CSV形式で保存してもいい driver.find_element_by_name("fwListNaviBtnNext").click() time.sleep(5) # 今見ているページをBeautifulSoupで解析 soup = BeautifulSoup(driver.page_source, "html.parser") # 「求人」のテーブルを検索 jobs = soup.find_all("table", attrs={"class": "kyujin"}) # 検索結果を格納する"message"を初期化 message = "" # 「職種」「月給」「勤務地」「仕事の内容」を取得する for i, job in enumerate(jobs): job_name = str(job.find("td", attrs={"class": "m13"}).text.strip()) salary_tags = job.find_all("tr",attrs={"class": "border_new"})[5].select(".disp_inline_block") for t, salary_tag in enumerate(salary_tags): job_salary = salary_tag.text # 月給の上限の金額を正規表現で抽出 m = re.search('(〜)(\d{3}),(\d{3})', job_salary) highest = int(m.group(2) + m.group(3)) # 月給の上限の金額が40万円以上だった場合にのみ、"message"に格納する if highest >= 400000: print("〇 ", highest) job_description = job.find(string='仕事の内容').parent.find_next_sibling().text.replace('\n', '') job_location = job.find(string='就業場所').parent.find_next_sibling().text.replace('\n', '') message = message + "■{0} ( {1} ){2} \n□{3}\n".format(job_name, job_salary, job_location, job_description) else: print("× ", highest) # 検索結果の出力 print(message) # driver.close()
実行結果(一応、伏字で伏せています):
■************在宅勤務を導入中◆(○○市) ( 250,000円〜500,000円 )○○県○○市○○区 □************WEB言語を使用。設計済みで開発をメイン工程。 ■************在宅勤務を導入中◆(○○市) ( 250,000円〜500,000円 )○○県○○市○○区 □************WEBへの新規展開に向けたリプレースPJです。 ■************務可) ( 202,000円〜580,000円 )○○県○○市○○区 □************ネット関連ソフト開発 ■************在宅勤務可) ( 202,000円〜580,000円 )○○県○○市○○区 □************上心のあるエンジニアの求人です。 ■************ ( 220,000円〜400,000円 )○○県○○市○○区 □************(言語:C,C**、C#、JAVA,VB、PHP等) ■************(正)/○○区 ( 250,000円〜460,000円 )○○県○○市○○区 □************製造、テスト :
ハローワークインターネットサービスで仕事を検索すると、不便なことがあります。
まず、1ページに50件までしか表示できないので、検索結果が比較しづらいですね。
あと、以前は給与で検索できたのですが、今は廃止されたようです。
まぁ、元々、200,000円~500,000円みたいな給与の幅で提示されているんで、
給与で検索してもあまり意味が無い、という理由もあったと思います。
それでも、やっぱり一定金額以上の給与のみを表示できると便利ですよね。
ということで、PythonのSeleniumとBeautifulSoupを使って
ハローワークから自動的に検索結果を取得(スクレイピング)することにしました。
ただ、1から自分で作ったのではなく、
以下の記事を基に書きました
(作者の齊藤さん、この場をお借りしてありがとうございます!):
そして、自分のニーズに合わせて、幾つかの項目を追加しました。
その際には、以下の回答を参考にしました:
例えば、複数の勤務地を選択してみました。
ご自分で勤務地を変更する場合は、勤務地の市町村コードを以下から見つけて下さい:
www13.plala.or.jp www13.plala.or.jp
あと、PythonとC#をキーワードとしてOR検索したり、
月給の上限が40万円以上の案件しか表示しないようにしてあります。
私が付け加えた部分については、後日コードの説明を追記する予定です。
また、齊藤さんの記事に元々ある部分については、
私は説明を控えますので、齊藤さんの記事をご覧ください。
注意書きですが、検索で見つかった求人情報は
ハローワークインターネットサービスに掲載されているサイトポリシーに沿ってご利用下さい:
www.hellowork.mhlw.go.jp
また、ハローワークインターネットサービスのレイアウトが変更されれば、
私のコードも動作しなくなるのでご注意ください。
(レイアウトが変更されたからといって、
ハローワークインターネットサービスに問い合わせないで下さいね。)
もし、私の記事を基にご自分のニーズに合った改造が出来たなら、
履歴書に「Pythonでスクレイピングが出来ます」と書いてもよいのではないでしょうか?
皆様のお仕事探しの助けになれば光栄です。
・・・以上です。
自己紹介
はじめまして!
ai_makerと申します。
ブログを書くのは久しぶりです。
私の知識を皆さんと共有できたらと思い、書き始めました。
内容としては、主にプログラミング、数学、英語、音楽になると思います。
映画とかドラマについての雑談も話してしまうかもです。
皆さんからのご指摘があれば勉強させていただきたいなと思います。
では、今後ともよろしくお願いします。