COMPANY SERVICE STAFF BLOG NEWS CONTACT

STAFF BLOG

スタッフブログ

TECHNICAL

テクログ

2022.07.19

PythonでJOBCANをスクレイピングしてデータを取得する

テクログpython

お久しぶりです。Python初心者のたかしです。
日頃の業務ではコードを書く機会が少なくなっていたので、久々のコーディングで楽しかったです。

制作の背景

毎月の月末、交通費を申請する際にJOBCANをみて「今月は何回出社したか」を数えています。
でも一覧ページなどでパッと確認ができず、日付詳細ページまで遷移しないと確認ができないので時間がかかります。
なので出社日数を自動でカウントしてくれるものを作ってみました。

普段は業務でPHPを使っていますが、以下の記事を見てみると簡単にできそうだったので、
触れたことはなかったですが、Pythonで作ることにしました
参考にした記事:https://zenn.dev/mamekko/articles/ea44fe8a77da7c

できたもの

1日ごとの勤務地と当月の合計値を出力するようにしました。

作業前提

・自分の端末はMacである

・自分のMacにはPython3が入っていなかった

・homebrewは入っていた(もちろん業務で使うので)

作業手順① pythonをbrewでインストールします

brew install python

インストール完了次第、pythonがローカルで動くか確認します。

print("Hello")

上記のようなテスト実行できるファイルをデスクトップに用意します。

cd Desktop
python hello.py

実行してみます

zsh: command not found

上記エラーが出ました。
どうやらパスが通ってないので、通してあげる必要がある。

/Users/t.coretech  ここで

vi .zshrc

以下を貼り付け、保存する

# PYTHON_HOMEにインストールしたpythonのパスを指定する
export PYTHON_HOME="/Library/Frameworks/Python.framework/Version/3.9/bin"
export PATH="$PYTHON_HOME:$PATH"

# pythonコマンドでpython3が起動するにようにaliasを設定
alias python='python3'
alias pip='pip3'

参考にした記事:https://qiita.com/yuuman/items/90d9253c52ee35f91d66
参考にした記事:https://dev.classmethod.jp/articles/python-commands-give-me-not-found-errors/

ターミナルを再起動して、
python hello.pyを実行してみると “Hello” が出力されました。これでPythonのインストール終わり。

作業手順② スクレイピングで使うライブラリをインストールします

pip install requests
pip install beautifulsoup4

ライブラリが動くか確認します。

import requests
from bs4 import BeautifulSoup

# ログイン前のurl
login_url = "{url}"
response = requests.get(login_url)
soup = BeautifulSoup(response.text, 'lxml')
python login.py   (/Users/t.coretech/Desktopで実行)

以下エラーがでました。

bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library?

以下コマンドで直りました。参考記事:https://qiita.com/ysuzuki19/items/330065ae1fe420f200fd

pip3 install lxml

ログインできるか試してみる

import requests
from bs4 import BeautifulSoup

# ログイン前のurl
login_url = "https://ssl.jobcan.jp/login/pc-employee-global?err=1&lang_code="

session = requests.session()
payload = {
  "client_id"      : "XXXXXXXX",
  "email"          : "XXXX@example.jp",
  "password"       : "XXXXXXXXX",
  "save_login_info": "0",
  "url"            : "https://ssl.jobcan.jp/employee/attendance",
  "login_type"     : "1",
  "lang_code"      : "ja"
}
r = session.post(login_url, data=payload)
soup = BeautifulSoup(r.content, "lxml")
print(soup)
python login.py   (/Users/t.coretech/Desktopで実行)

上記でJOBCANにログインした後のテキストが出力されていればOKです。

コーディング内容

① 以下JOBCAN URLの末尾の1を月末まで変えてあげれば、月の全てのページを辿れます
 https://ssl.jobcan.jp/employee/adit/modify?year=2022&month=6&day=1 

② 以下画像の箇所で在宅勤務かリモート勤務かを判定します

import requests as req
from bs4 import BeautifulSoup
import time

# ログイン前のurl
login_url = "https://ssl.jobcan.jp/login/pc-employee-global?err=1&lang_code="

# requestsを使った、セッション使用開始
session = req.session()

payload = {
  "client_id"      : "XXXXXXXX",
  "email"          : "XXXX@example.jp",
  "password"       : "XXXXXXXXX",
  "save_login_info": "0",
  "url"            : "https://ssl.jobcan.jp/employee/attendance",
  "login_type"     : "1",
  "lang_code"      : "ja"
}

# ログインフォームに対して必要情報を送る
r = session.post(login_url, data=payload)

# JOBCANの調査したい月と月末日を設定する(7月ならmax_daysは31に変えてください)
year = 2022
month = 6
max_days = 30

urls = list()
for day in range(max_days) :
  url = "https://ssl.jobcan.jp/employee/adit/modify?year=" + str(year) + "&month=" + str(month) + "&day=" + str(day+1)
  urls.append(url)

# 結果の出力で必要な変数を定義
d = 0
office_work_count = 0
myhome_work_count = 0

# 月始めのURLから月末のURLまでをforで回す
for url in urls :

  # 速度調整で1.5秒
  time.sleep(1.5)

  res = session.get(url)
  soup = BeautifulSoup(res.text, "lxml")
  # 打刻がない日は、以下 soup_list が空配列(空リスト)になります
  soup_list = soup.select(".align-middle")

  # デフォルト値
  ans = "休み"

  i = 0
  for soup in soup_list :

    i += 1
    # .align-middle を使っている箇所が多すぎるので、検証したい箇所(3つめのalign-middle)だけifを通す
    if i == 3 :

      txt = soup.get_text()

      if txt == "ICカード(iOS)" :
        ans = "オフィス勤務"
        office_work_count += 1
        break
      elif txt.find("GPS") is not None :
        ans = "在宅勤務"
        myhome_work_count += 1
        break
      else :
        print("異常です。プログラムを確認してください")

  d += 1
  print(str(month) + "月" + str(d) + "日 " + ans)

print("オフィス勤務合計" + str(office_work_count))
print("リモート勤務合計" + str(myhome_work_count))

上記のコードで正しく動いてくれてました。
これから申請がラクになりそうです。

【Python初心者の自分が参考にした記事】
soup.select():https://gammasoft.jp/blog/difference-find-and-select-in-beautiful-soup-of-python/
末尾に要素を追加: append:https://note.nkmk.me/python-list-append-extend-insert/
PHPでいうfor ++:https://atmarkit.itmedia.co.jp/ait/articles/1905/10/news023_2.html#forandrange
findは見つからなかったらNoneを返す:https://yu-nix.com/archives/beautifulsoup4-find/#%E5%89%8D%E6%8F%90%E3%81%A8%E3%81%99%E3%82%8BHTML
基礎:結合演算子:https://note.nkmk.me/python-string-concat/

終わりに

普段PHPしか触っていない自分ですが、これくらいの量のPythonなら割と簡単でした。
int で文字結合しようとすると怒られるのは新鮮でしたw

やっぱり自分で書くのは楽しい。

これから猛暑続きですが、美味しいジュースでも飲んで乗り切りましょう。では。

この記事を書いた人

たかし

入社年2020年

出身地和歌山

業務内容WEB制作

特技・趣味YouTubeみること

テクログに関する記事一覧

TOP