Open18

Pythonのユースケースと便利な書き方やライブラリをまとめる

nabetsunabetsu

配列同士の組み合わせを作成する

以下のような組み合わせを作りたい。
最初はzipでやることも考えたが要素数が異なると困る?のではと思って便利なやり方がないか調べたところitertools を使えば簡単に実現できそうだった。

sample1 = [1, 2]
sample2 = [3, 4]
>> [(1, 3), (1, 4), (2, 3), (2, 4)]

実現方法

itertoolsのproductを使う。

import itertools

sample1 = [1, 2]
sample2 = [3, 4]

list(itertools.product(sample1, sample2)) # [(1, 3), (1, 4), (2, 3), (2, 4)]

itertoolsには他にも便利な機能がありそう。

nabetsunabetsu

配列で重複していない要素を求める

a = [1, 2, 3]
b = [1, 2, 3, 4, 5]

set(b)^set(a) # {4, 5}
nabetsunabetsu

JSON

JSONファイルの出力・書き出し

ファイルへの書き出し

json.dumpを使う。
オプション等は基本的にjson.dumpsと同様

import json

with open('sample.json', 'w') as f:
    json.dump(texts, f, indent=4, ensure_ascii=False)

json.dumpsで対応していない型をJSON文字列に変換する

日付(datetime)などはJSONの型として定義されていないため、json.dumpsで変換しようとすると以下のようなエラーが出てしまう。

TypeError: Object of type 'datetime' is not JSON serializable

参考資料にあるように、変換方法を定義して、json.dumpsの際にそれを使うよう指定すれば変換が行える。

書き出したファイルの読み込み

json.loadsを使って読み込んだものをDictionaryに変換すればいい。

with open('sample.json',) as f:
    scrap_data = json.loads(f.read())

参考資料

nabetsunabetsu

日付関係の処理

datetimeオブジェクト

datetime.nowで現在の日付を取得できる。

import datetime

# now()で現在時刻を取得できる
now = datetime.datetime.now()
now # datetime.datetime(2021, 10, 30, 17, 26, 24, 530596)

# datetimeオブジェクトはmonthやyearなどのプロパティにアクセスできる
print(now.year) # 2021
print(now.month) # 10
print(now.day) # 30

文字列への変換

datetimeオブジェクト.strptimeで文字列に変換できる。

now.strftime('%Y/%m/%d')

文字列から日付型への変換

strftimeで文字列から日付型への変換ができる。

str_now = now.strftime('%Y/%m/%d')
datetime.datetime.strptime(str_now, "%Y/%m/%d") # datetime.datetime(2021, 10, 30, 0, 0)

ISOフォーマットの取り扱い

.isoformatでISOフォーマットの文字列に変換できる。

# datetimeを文字列に変換
now.isoformat() # 2021-10-30T17:26:24.530596

文字列→日付型の変換はfromisoformatでできるはずだが、isoformatで変換した文字列が変換できない...

datetime.date.fromisoformat(now.isoformat()) # ValueError: Invalid isoformat string: '2021-10-30T17:13:07.087418'

dateutil.parserを使えばdatetimeとして読み込める。

import dateutil.parser

dateutil.parser.parse(now.isoformat()) # datetime.datetime(2021, 10, 30, 17, 26, 24, 530596)

AirtableのAPIから取得したZが含まれるISOフォーマットでも問題なく読み込める。

test_data = res.json()
test_data['records'][14]['fields']["Date"] # 2021-10-30T16:04:07.432Z
dateutil.parser.parse(test_data['records'][14]['fields']["Date"]) # datetime.datetime(2021, 10, 30, 16, 4, 7, 432000, tzinfo=tzlocal())

参考資料

前月を取得する

以下のコードで前月が取得できる

# ライブラリのインポート
import datetime

# 今日を取得
today = datetime.datetime.today()
print(today.strftime("%Y-%m-%d"))

# 当月1日の値を出す
thismonth = datetime.datetime(today.year, today.month, 1)
print(thismonth.strftime("%Y-%m-%d"))

# 前月末日の値を出す
lastmonth = thismonth + datetime.timedelta(days=-1)
print(lastmonth)

# フォーマットを指定して、年月だけ拾う
print(lastmonth.strftime("%Y%m"))

以下の資料をそのまま使っただけ。

Pythonで先月を取得する - Qiita

nabetsunabetsu

複数ファイルの連結

  • 複数のファイルを連結したいケース。
    具体的な使用例として自然言語処理のデータセットでデータセットが個別のテキストファイルに分かれているケースでの連結に使用
import glob

read_files = glob.glob("*.txt")

with open("result.txt", "wb") as outfile:
    for f in read_files:
        with open(f, "rb") as infile:
            outfile.write(infile.read())

python - Pythonを使用して複数のテキストファイルを1つのテキストファイルに結合する[複製] - ITツールウェブ

nabetsunabetsu

ソート

  • ソートする
  • リストを逆順にする
    • 特定の項目でのソートではなく、単純に順番を逆にする方法。
      ユースケースとして、APIの返りが新しいレコード順の場合に古い順に変更するなど
    • 選択肢
      • reverse
        • 元のリストの内容を変更する破壊的な関数
org_list = [1, 2, 3, 4, 5]

org_list.reverse()
print(org_list)
# [5, 4, 3, 2, 1]```
        - `reversed`
            - 元のリストの内容は変更せず、イテレータを返す非破壊的な関数
        - スライス
            - スライスを活用しても同様のことが実現できる
            - ```python
org_list = [1, 2, 3, 4, 5]

new_list = org_list[::-1]
print(org_list)
print(new_list)
# [1, 2, 3, 4, 5]
# [5, 4, 3, 2, 1]```
    - コード
        - ```python
sorted_tweet_list = reversed(search_tweets)
sorted_tweet_list # <list_reverseiterator at 0x10c9b1c70>
nabetsunabetsu

URLやクエリパラメータの扱い

Pythonの標準ライブラリであるurllib はリクエストを送信したり、URLをパースするための便利な機能を提供している。

URLの連結

urllib.parseurljoinを使うことで、ドメインと相対URLから絶対URLを簡単に生成することができる。
具体的なユースケースとしてはスクレイピングでaタグのhrefから相対URLを取得した後、対象ページのURLと組み合わせることで次のスクレイピング対象のページを絶対URLで取得する場合など。

import urllib.parse

base_url = 'https://www.example.com'
relative_url = '/sample/test'
urllib.parse.urljoin(base_url, relative_url) # https://www.example.com/sample/test

base_url = 'https://www.example.com/'
relative_url = '/sample/test'
urllib.parse.urljoin(base_url, relative_url) # https://www.example.com/sample/test

クエリパラメータ

クエリパラメータを含んだURLからクエリパラメータの部分を抜き出して中身を変えたり、Dictionaryからクエリパラメータを生成したりすることができる。

  • parse_qs
    • URLの文字列を渡すことでクエリパラメータを抜き出してくれる
  • urlencode
    • Dictionaryを渡すことでクエリパラメータを文字列に変換してくれる

参考資料

PythonでURLのクエリ文字列(パラメータ)を取得・作成・変更 | note.nkmk.me

nabetsunabetsu

文字列関係

基本文法

文字列が含まれているか確認する

文字列の中に任意の文字列が含まれているか判定・確認するにはin演算子を使う。含まれているとTrue、含まれていないとFalseを返す。


記号を削除する

空白を取り除く

replaceを使うと色々な方法があるが、まとめて余計なものを消したいなら以下の正規表現を使うのが簡潔でわかりやすい気がする。

import re

#改行、タブ、スペースなどをまとめて削除
text = "a\u3000\n\n b\t\nc\r\nd\x0ce\x0b\rf\r\n"
text = re.sub(r"\s", "", text)

#改行コード(\r\nや\n)だけをまとめて削除
text = "a\u3000\n\n b\t\nc\r\nd\x0ce\x0b\rf\r\n"
text = re.sub(r"[\r\n]", "", text)

#いくつかのスペース(例えば全角スペース、半角スペース、タブ)をまとめて削除
text = "a\u3000\n\n b\t\nc\r\nd\x0ce\x0b\rf\r\n"
text = re.sub(r"[\u3000 \t]", "", text)

いろんな空白文字を削除する【Python】 - Qiita

参考資料

正規表現

数字だけを残す

カンマや¥など余計ば文字列を省いて数字だけを抽出する方法。

content = '¥2,640 税込'
pattern = '[^0-9\n]|^\n'

result = re.sub(pattern, "", content)
print(result) # 2640
content = '¥2,640 税込'
pattern = '\D'

result = re.sub(pattern, "", content)
print(result)
nabetsunabetsu

Listの扱い

配列同士を比較

  • 並びも含めて同一性を確認したい場合
    • Listのまま==で比較
  • 要素が含まれているかだけ確認したい場合
  • setに変換して比較

Pythonのリストを比較する方法 | HEADBOOST

Dictionaryの配列を結合

data = [
         {'name' : 'John'}
]

data1 = [
         {'name' : 'Tom'}
]

print(data + data1) # [{'name': 'John'}, {'name': 'Tom'}]
print(data.extend(data1)) None
nabetsunabetsu

Collection Types

Dataclass

dataclasses.asdictを使うことでdictionaryとして出力できる。

dataclasses.asdict
nabetsunabetsu

Dictionaryを検索

アプローチとして以下の3つ?

  • リスト内包表記
  • filterの利用
list(filter(lambda item: item['url'] in newly_added_urls, all_pages))

特定のキーを元にソート

sorted(l, key=lambda x: x.get('Point', 75))

参考資料

nabetsunabetsu

基本演算

合計を出力

組み込み関数のSumを使うのがいい。

myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
listSum = sum(myList)
print(f"Sum of list -> {listSum}")