スクレイピングをすると、時刻であっても文字列型で取得されてしまう。
海外のサイトであれば、日本時刻ではなく、イギリスの時刻で取得されてしまうことも多く、何とか日本時刻に変換をしたい。
そんなことがあったので、僕が実際に解決した方法を忘備録もかねて紹介しておきます。
Pythonを独学で勉強していたり、Pythonで稼ごうと考えているのであればぜひとも当ブログをブックマークしておくことをおすすめします!
この記事の内容
- Pythonで時刻を加算する方法
- datetimeモジュールでできること・使い方
- datetimeで文字列型からdatetime形に変換する方法
- datetimeでdatetime型から文字列型に変換する方法
- datetimeでスクレイピングした日時に時差を加味させる方法
Pythonで時刻を加算する方法
Pythonで時刻をスクレイピングをしたとき、海外のサイトだと時差が生じてしまって、日本時刻ではない時刻をスクレイピングしてしまうことも少なくないです。
僕もNBAの試合日程を毎日LINEで通知するプログラムを作成したときに、どうしても変な時間を取得してしまっていました。
しかし、そんな時datetimeモジュールを使うことで解決することができたので、忘備録を兼ねて紹介します。
文字列からdatetime型へ変換する方法や、時差の計算、〇時間後や〇日後の取得をしたい人はこの先の記事を参考にしてみてください。
Pythonの時刻を操作するパッケージdatetimeをマスターする
Pythonで時刻の加算をするには、まずdatetimeモジュールを使うのが絶対条件です。
datetimeモジュールを使うと、文字列を日時としてPythonが認識してくれるようにできたり、今何時?と聞いて答えてくれたりします。
そのためdatetimeの使い方をマスターすることで時刻を加算できるようになります。
まずはdatetimeの基本的な使い方からマスターしましょう!
datetimeでできること
- 現在の日時を取得する
- 取得した日時のフォーマットを変更する
- 日付の加算減算をする など
datetimeモジュールが持つ3つのクラスを理解する【datetime,date,time】
datetimeモジュールには、さらにdatetime型、date型、time型が存在しており、それぞれの型で日付や時刻の表し方が異なります。
まずは、3つの違いを理解することでこの記事の理解度が高まりますので抑えておきましょう。
datetimeクラス
print(datetime.datetime.now()) print(type(datetime.datetime.now())) 2022-12-17 07:33:55.139683 <class 'datetime.datetime'> print(datetime.date.today()) print(type(datetime.date.today())) 2022-12-17 <class 'datetime.date'> print(datetime.datetime.now().time()) print(type(datetime.datetime.now().time())) 07:33:55.144656 <class 'datetime.time'>
datetimeクラスは日付と時刻のどちらも合わせ持つクラスです。
文字列をdatetime型に変換したい場合などは、datetimeクラスが持つ、strptimeを使います。
その他にも、datetime.datetime.now()で現在の日時を求めることも可能です。
dateクラス
print(datetime.date.today()) print(type(datetime.date.today())) #2022-12-17 #<class 'datetime.date'>
dateクラスでは、年月日だけに絞った情報を持っているクラスです。
datetimeクラスだと、年月日のほかに時間がマイクロ秒までついてくるので逆に邪魔な時があります。そんな時は、datetimeクラスではなく、dateクラスで操作をしていくことがおすすめです。
timeクラス
print(datetime.datetime.now().time()) print(type(datetime.datetime.now().time())) #07:35:10.294288 #<class 'datetime.time'>
timeクラスは、「〇時〇分〇秒〇マイクロ秒」の情報を持ったクラスです。
年月日は必要ない!今の時間だけが知りたい!なんてときにはdatetimeクラスでもdateクラスでもなく、timeクラスを使ってあげると便利です。
現在の日時を取得する
datetimeを使うと現在の日時を一瞬で取得することができます。
文字列型(str) ⇔ datetime型の変換方法
文字列をdatetime型に変換するときは、datetimeが持つstrptimeメソッドを利用します。
【datetime.datetime.strptime(str,'format')】でstr型からdatetime型に変更することができます。
データの型が違うことが原因で起こるエラーが多数あります。
その一つが文字列型とdatetime型の違いで起こるミスです。
文字列(str)型からdatetime型への変換【strptimeメソッド】
import datetime
str = '12/16(Thu)0:00' type(str) #str time = datetime.datetime.now() type(time) #datetime.datetime
文字列を表すデータ構造をPythonでは「str型」と呼び、時刻や日付を表すデータ構造を「datetime型」と呼びます。
str型はあくまで文字列なので、「1+1 = 2」と計算したい場合も、文字列足す文字列だと、「1 + 1」は「11」になってしまします。
数値計算をしたい時は、「int型」に変更する必要があります。
すなわち、時刻を0:00を9:00に変換したい場合は、str = '12/16(Thu)0:00'をdatetime型に変換する必要があります。
datetime型から文字列型(str型)への変換方法【strptimeメソッド】
str = '12/16(Thu)0:00' print(str) print(type(str)) #12/16(Thu)0:00 #<class 'str'> date = datetime.datetime.strptime(str,'%m/%d(%a)%H:%M') print(date) print(type(date)) #1900-12-16 00:00:00 #<class 'datetime.datetime'>
Pythonでstr型からdatetime型へ変換するときは、datetime.datetimeオブジェクトが持っている「strptimeメソッド」を使います。
使い方は、「datetime.datetime.strptime(文字列,フォーマット)」で変換できます。
フォーマットとは、何処が月で何処が日にち、どこが時刻なのかをPythonに伝える暗号で、%mや%dを使います。
僕が主に使うフォーマットは以下の表です。
datetimeでの覚えるべきフォーマット
書き方 |
Pythonに伝わる意味 |
%a | ロケールにおける省略形の曜日名。
Mon,Thu など |
%A |
ロケールにおける省略なしの曜日名。 Monday,Thuesday など |
%H |
(24 時間計での) 時を表す 10 進数 00時~23時 0を消したいときは。「%-H」と表現する。 |
%I |
(12 時間計での) 時を表す 10 進数 01時~12時 0を消したいときは。「%-I」と表現する。 |
%m |
月を表す 10 進数 01月~12月0を消したいときは。「%-m」と表現する。 |
%M |
分を表す 10 進数 00分~59分 0を消したいときは。「%-M」と表現する。 |
%w |
曜日を表す 10 進数 0(日曜日),1(月曜日)・・・6(土曜日) |
%W |
年の初めから何週目か (日曜を週の始まりとします)を表す。 10 進数 [00,53]。年が明けてから最初の月曜日までの全ての曜日は 0 週目に属すると見なされます。 |
%x |
ロケールにおける適切な日付の表現。 |
%X |
ロケールにおける適切な時刻の表現。 |
%y |
上 2 桁なしの西暦年を表す 10 進数 |
%Y |
上 2 桁付きの西暦年を表す 10 進数。 |
%Z |
タイムゾーンの名前 (タイムゾーンがない場合には空文字列)。 |
%% |
文字 “%” 自体の表現。 |
datetime型の加算減算する方法【時差の計算に便利】
datetimeで時差を計算するときは、datetimeクラスが持つ「timedeltaメソッド」を用いることで計算できます。
基本的な型は「datetime型 + timedeltaで設定した日時」です。
import datetime kijun = datetime.datetime.now() print(kijun) #2022-12-17 06:43:18.481541
例えば、日本時間で15時43分にdatetime.datetime.now()を実行すると、上記のように、6時43分が出力されます。
基準時間はイギリスなので日本時間よりも-9時間されてしまうわけです。
そのため、日本時間をただしく表示させたければ、+9時間する必要があります。そんな時に、timedeltaを使います。
timedelta(時間)で、時間を表現することができます。今回は9時間を表現したかったので、「timedelta(hours=9)」とすることで9時間を表現しています。
ほかにも以下のように表現ができます。
timedeltaでできること | timedeltaの引数 |
年を加算する |
timedelta(years=1) |
月を加算する | timedelta(weeks=1) |
日にちを加算する |
timedelta(days=1) |
時間を加算する | timedelta(hours=1) |
分を加算する | timedelta(minutes=1) |
秒を加算する | timedelta(seconds=1) |
1年と3時間加算する(複数も指定可能) | timedelta(years=1,hours=3) |
実用例:スクレイピングした日付の時差を計算する
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver import ChromeOptions import requests import time import datetime import pytz now = datetime.datetime.now(pytz.timezone('Asia/Tokyo')) now.date() today_date = now.date().strftime('%Y%m%d') options = ChromeOptions() options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') browser = webdriver.Chrome('chromedriver',options = options) browser.get('https://sports.yahoo.co.jp/basket/nba/schedule/reg?date=20221219') time.sleep(2) #ifram内をスクレイピングするための宣言 iframe = browser.find_element(By.ID,"widget-schedule") browser.switch_to.frame(iframe) #リストを用意 hometeam_ls = [] awayteam_ls = [] game_ls = [] #試合日程の取得 #1試合の情報が入っている要素ブロックを全部取得 game_elem = browser.find_elements(By.CSS_SELECTOR,'#js-widget > div > section > table > tbody > tr') #各試合の要素から必要な情報を取得 for game in game_elem: #試合の日時を取得 gamedate = game.find_element(By.CSS_SELECTOR,'td.ba-tableGame__data.ba-tableGame__data--date').text #試合の日時を整形 if gamedate[-5] == '\n': b = gamedate[-4:] else: b = gamedate[-5:] #日本時間に変更 b = datetime.datetime.strptime(b,'%H:%M') + datetime.timedelta(hours=9) gamedate = b.strftime('%-I:%M') #チーム名取得 hometeam = game.find_element(By.CSS_SELECTOR,'td:nth-child(2)').text awayteam = game.find_element(By.CSS_SELECTOR,'td:nth-child(4)').text #必要な情報をリスト型にまとめる game_ls.append(gamedate+' ' + hometeam+'VS'+awayteam) hometeam_ls.append(game.find_element(By.CSS_SELECTOR,'td:nth-child(2)').text) awayteam_ls.append(game.find_element(By.CSS_SELECTOR,'td:nth-child(4)').text) #最終的にメッセージ分にまとめる game_schedule = '\n'.join(game_ls) print(game_schedule) ''' 出力結果 5:00 セルティックスVSマジック 7:00 ペイサーズVSニックス 8:00 ラプターズVSウォリアーズ 8:00 ピストンズVSネッツ 9:00 ティンバーウルブズVSブルズ 10:00 ナゲッツVSホーネッツ 11:30 レイカーズVSウィザーズ '''
実際に僕がこの記事を書くきっかけとなったケースを紹介します。
ある時NBAの試合情報をスポナビから取得しようとしたときのこと。Webサイト上では9:00の表記になっているにも関わらず、スクレイピングをしてみると0:00とイギリス時間で取得されてしまった。
しかもスクレイピング舌データは文字列型で取得されてしまったので、どうにか9:00に変換したい。というケースです。
詳しいコードの解説はこちらの記事で行っていますので、よかったらチェックしてみてください!
まとめ:Pythonの可能性は無限大
Pythonでできないことはないのではないかと思った今日このごろでした。
まず独学でも習得しやすくて汎用性の高いスキルが「スクレイピング」です。
僕がPythonで初めて1円を稼いだのもクラウドソーシングでスクレイピングの案件に応募したことがきっかけでした。
もしPythonで1円でも稼げたらいいなと思っているのであれば「スクレイピング」のスキルを身に付けるところから初めてみるのもおすすめです!
スクレイピングのスキルを習得するコツはこちらの記事でまとめているので良かったら参考にしてみてください!