日付時刻
datetime は、日付と時刻を処理するための Python の標準ライブラリです。
現在の日付と時刻を取得する
from datetime import datetime
now = datetime.now() # 获取当前datetime
print(now) #2023-09-13 10:28:48.621343
print(type(now))#<class 'datetime.datetime'>
- インポートされるのは datetime クラスである
datetime是模块
ことに注意してください。from datetime import datetime
- import datetime のみをインポートする場合は、引用符を付ける必要があります
全名datetime.datetime
- import datetime のみをインポートする場合は、引用符を付ける必要があります
指定した日時を取得する
dt = datetime(2023, 9, 13, 12, 20) # 用指定日期时间创建datetime
print(dt)
日時をタイムスタンプに変換する
- コンピュータでは、時間は実際には
数字
という単位で表されます。1970 年より前の時刻として記録された1970年1月1日 00:00:00 UTC+00:00
タイム ゾーンの瞬間を と呼びます(タイムスタンプは負の数です)。現在の時刻は を基準としたものであり、タイムスタンプと呼ばれます。epoch time
0(
epoch time的秒数
dt = datetime(2023, 9, 13, 12, 20) # 用指定日期时间创建datetime
print(dt.timestamp()) # 把datetime转换为timestamp
#1694578800.0
- Python のタイムスタンプは 1 であることに注意してください
浮点数,整数位表示秒
。
タイムスタンプは、UTC 標準タイムゾーンに直接変換することもできます。
t = 1429417200.0
print(datetime.fromtimestamp(t)) # 本地时间
#2015-04-19 12:20:00
print(datetime.utcfromtimestamp(t)) # UTC时间
#2015-04-19 04:20:00
str を datetime に変換する
- datetime.strptime() を通じて実装され、日付と時刻の書式設定された文字列が必要です。
cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
print(cday)
#2015-06-01 18:19:59
datetime を str に変換する
now = datetime.now()
print(now.strftime('%a, %b %d %H:%M'))
#Mon, May 05 16:28
日時の加算と減算
- 日付と時刻の加算と減算は、実際には
datetime往后或往前计算
新しい日時を取得することです。加减可以直接用+和-运算符,不过需要导入timedelta这个类
:
from datetime import datetime, timedelta
now = datetime.now()
datetime(2023, 9, 13, 10, 30, 3, 540997)
print(now + timedelta(hours=10))#2023-09-13 20:38:44.709003
datetime(2023, 9, 13, 10, 30, 3, 540997)
print(now - timedelta(days=1))#2023-09-12 10:38:44.709003
datetime(2023, 9, 13, 10, 30, 3, 540997)
print(now + timedelta(days=2, hours=12))#2023-09-12 10:38:44.709003
現地時間を UTC 時間に変換する
from datetime import datetime, timedelta, timezone
tz_utc_8 = timezone(timedelta(hours=8)) # 创建时区UTC+8:00
now = datetime.now()
print(now)
dt = now.replace(tzinfo=tz_utc_8) # 强制设置为UTC+8:00
print(dt)
dt = datetime(2015, 9, 13, 10, 40, 13, 610986, tzinfo=timezone(timedelta(0, 28800)))
print(dt)
タイムゾーンの変換
from datetime import datetime, timedelta, timezone
# 拿到UTC时间,并强制设置时区为UTC+0:00:
utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
print(utc_dt)
# astimezone()将转换时区为北京时间:
bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
print(bj_dt)
# astimezone()将转换时区为东京时间:
tokyo_dt = utc_dt.astimezone(timezone(timedelta(hours=9)))
print(tokyo_dt)
# astimezone()将bj_dt转换时区为东京时间:
tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9)))
print(tokyo_dt2)
まとめ
-
datetime で表される時刻には、特定の時刻を決定するためのタイム ゾーン情報が必要です。そうでない場合は、ローカル時刻としか見なされません。
-
datetime を保存したい場合は、それを使用するのが最善の方法です
转换为timestamp再存储,因为timestamp的值与时区完全无关
。
Base64
Base64 は、テキスト文字列を任意のバイナリ形式に変換するためのエンコード方式で、URL、Cookie、および Web ページで一般的に使用されます传输少量二进制数据
。
-
Base64 の原理は非常に単純で、まず 64 文字を含む配列を準備します。
['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']
-
次に、バイナリ データが処理され、
每3个字节一组
合計3x8=24bit
4 つのグループに分割されます。各グループは正確に次のとおりです6个bit
。 -
このようにして、インデックスとして 4 つの数値を取得し、その後、
查表
エンコードされた文字列である対応する 4 つの文字を取得します。-
したがって、 Base64エンコード
会把3字节的二进制数据编码为4字节的文本数据,长度增加33%
の利点は、エンコードされたテキストデータをメールやWebページなどの本文に直接表示できることです。 -
エンコードするバイナリ データが 3 の倍数ではなく、最後に 1 バイトまたは 2 バイトが残る場合はどうなるでしょうか?
- Base64 は最後のパディングの後に使用され、
\x00字节
エンコーディングの最後に上1个或2个=号,
パディングされるバイト数を示します解码的时候,会自动去掉
。
- Base64 は最後のパディングの後に使用され、
-
Python の組み込み Base64 は、base64 を直接エンコードおよびデコードできます。
import base64
#`b'str'`可以表示字节,
a = base64.b64encode(b'binary\x00string')
print(a)
b = base64.b64decode(b'YmluYXJ5AHN0cmluZw==')
print(b)
#b'YmluYXJ5AHN0cmluZw=='
#b'binary\x00string'
b'str'
バイトを表すことができます。
これは標準の Base64 エンコーディングの後に現れる可能性があるため字符+和/
、URL のパラメータとして直接使用することはできません。そのため"url safe"
、実際には次のような別の Base64 エンコーディングが存在します把字符+和/分别变成-和_
。
#`b'str'`可以表示字节,
c= base64.b64encode(b'i\xb7\x1d\xfb\xef\xff')
print(c)#b'abcd++//'
d = base64.urlsafe_b64encode(b'i\xb7\x1d\xfb\xef\xff')
print(d)#b'abcd++//'
e = base64.urlsafe_b64decode('abcd--__')
print(e)#b'abcd++//'
ハッシュリブ
MD5,SHA1
Python の hashlib は、などの一般的なダイジェスト アルゴリズムを提供します。
**要約アルゴリズムとは何ですか?
-
**ダイジェスト アルゴリズムは とも呼ばれます
哈希算法、散列算法
。要約アルゴリズムは、元のデータが改ざんされているかどうかを検出することを目的として、摘要函数f()
任意の長さから数据data
固定長を計算します。(通常は 16 進数の文字列で表されます)。摘要digest
-
ダイジェストアルゴリズムでデータが改ざんされているかどうかが分かる理由
- 集計関数が1つなので
单向函数
計算はf(data)
簡単ですが合格ですdigest反推data却非常困难
。さらに、元のデータを 1 ビット変更すると、まったく異なる計算結果が得られます。
- 集計関数が1つなので
アプリケーションシナリオ
- 記事を書きました。内容は「Python hashlib の使い方 - by Michael」という文字列で、この記事の要約は「 」として添付されています
2d73d4f15c0db7f5ecb321b6a65e5d6d
。誰かがあなたの記事を改ざんして「 」として公開した場合、 「 」に基づいて計算された要約は元の記事の要約と異なるためhow to use python hashlib - by Bob
、ボブがあなたの記事を改ざんしたことをすぐに指摘できます。how to use python hashlib - by Bob
MD5 は最も一般的なダイジェスト アルゴリズムです。非常に高速で、生成される結果は固定です128 bit/16字节
。通常は32位的16进制字符串
1 で表されます。次のように
import hashlib
md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?'.encode('utf-8'))
print(md5.hexdigest())
#d26a53750bc40b38b65a520292f69306
データ量が多い場合、はい分块多次调用update()
、最終的な計算結果は同じになります。
import hashlib
md5 = hashlib.md5()
md5.update('how to use md5 in '.encode('utf-8'))
md5.update('python hashlib?'.encode('utf-8'))
print(md5.hexdigest())
#d26a53750bc40b38b65a520292f69306
もう 1 つの一般的なダイジェスト アルゴリズムは、SHA1
SHA1 の呼び出しが MD5 の呼び出しとまったく同じであることです。SHA1 の結果は であり160 bit/20字节
、通常40位的16进制字符串
は で表されます。
import hashlib
sha1 = hashlib.sha1()
sha1.update('how to use sha1 in '.encode('utf-8'))
sha1.update('python hashlib?'.encode('utf-8'))
print(sha1.hexdigest())
#2c76b57293ce30acef38d98f6046927161b46a44
SHA256和SHA512
ただし、SHA1 よりも安全なアルゴリズムはあります越安全的算法不仅越慢,而且摘要长度更长
。
hmac
ハッシュアルゴリズムでは、データのハッシュ値を比較することで、データが正当であるかどうかを検証できます。たとえば、ユーザーのパスワードが正しいかどうかを判断するには、データベースに保存されているpassword_md5
比較計算結果を使用します。一貫性のある、ユーザーが入力したパスワードですmd5(password)
。
彩虹表
ハッカーが元のパスワードを推測できないようにするために哈希值
、ハッシュを計算する際、元の入力に基づいて計算するだけではなく、salt
同じ入力でも異なるハッシュを取得できるようにハッシュを追加する必要があり、これにより計算の難易度が大幅に高まります。クラックするハッカー。
-
ソルトが自分でランダムに生成された場合は、通常、 MD5 を計算するときにそれを使用します
md5(message + salt)
。しかし実際には、salt を「パスワード」と考えると、salt のハッシュは次のようになります。メッセージのハッシュを計算するとき、異なるパスワードに基づいて異なるハッシュが計算されます。ハッシュ値を検証するには、正しいパスワードも指定する必要があります。-
これは実際には
Hmac算法
、メッセージ認証のためのキー付きハッシュです。標準アルゴリズムを使用してハッシュを計算します把key混入计算过程中
。 -
カスタムのソルト追加アルゴリズムとは異なります
Hmac算法针对所有哈希算法都通用,无论是MD5还是SHA-1
。Hmac を使用して独自のソルト アルゴリズムを置き換えると、プログラム アルゴリズムがより標準化され、より安全になります。
-
Python に付属の hmac モジュールは、標準の Hmac アルゴリズムを実装します。hmac を使用してキーによるハッシュを実装する方法を見てみましょう。
import hmac
#原始数据
message = b'Hello, world!'
#密钥
key = b'secret'
h = hmac.new(key, message, digestmod='MD5')
# 如果消息很长,可以多次调用h.update(msg)
print(h.hexdigest())
#'fa4ee7d173f2d97ee79022d1a7355bcf'
- 受信キーとメッセージは両方とも であることに注意してください
bytes类型,str类型需要首先编码为bytes
。
叫んでいる
詳細については、「[Python] 入門からトップへ—ネットワーク リクエスト モジュール urlib と reuests のアプリケーション シナリオ (12)」を参照してください。
XML
XML を操作するには 2 つの方法がありますDOM和SAX
。
-
DOM は XML 全体をメモリに読み込んでツリーに解析するため、スペースを消費しますが、
内存大,解析慢
利点は使用できることです任意遍历树的节点
。 -
SAX は
流模式
、読み取り中に解析し、占有するため内存小,解析快
、欠点は私たちにあります需要自己处理事件
。 -
通常の状況では、DOM が大量のメモリを消費するため、SAX が優先されます。
start_element,end_element和char_data
SAX を使用して Python で XML を解析するのは非常に簡単で、通常はこれら 3 つの関数を準備して XML を解析することに注意します。
例: SAX パーサーがノードを読み取るとき:
<a href="/">python</a>
3 つのイベントが生成されます。
-
start_element イベント、読み取り時
<a href="/">
。 -
char_data イベント、読み取り時
python
。 -
end_element イベント、読み取り中
</a>
。from xml.parsers.expat import ParserCreate class DefaultSaxHandler(object): def start_element(self, name, attrs): print('sax:start_element: %s, attrs: %s' % (name, str(attrs))) def end_element(self, name): print('sax:end_element: %s' % name) def char_data(self, text): print('sax:char_data: %s' % text) xml = r'''<?xml version="1.0"?> <ol> <li><a href="/python">Python</a></li> <li><a href="/ruby">Ruby</a></li> </ol> ''' handler = DefaultSaxHandler() parser = ParserCreate() #start_element事件 parser.StartElementHandler = handler.start_element #end_element事件 parser.EndElementHandler = handler.end_element #char_data事件 parser.CharacterDataHandler = handler.char_data #解析 parser.Parse(xml)
の結果
sax:start_element: ol, attrs: { } sax:char_data: sax:char_data: sax:start_element: li, attrs: { } sax:start_element: a, attrs: { 'href': '/python'} sax:char_data: Python sax:end_element: a sax:end_element: li sax:char_data: sax:char_data: sax:start_element: li, attrs: { } sax:start_element: a, attrs: { 'href': '/ruby'} sax:char_data: Ruby sax:end_element: a sax:end_element: li sax:char_data: sax:end_element: ol
- 大きな文字列を読み取る場合は、複数回呼び出される可能性があるため、の中にマージする必要があることに注意してください。
CharacterDataHandler
自己保存起来
EndElementHandler
- 大きな文字列を読み取る場合は、複数回呼び出される可能性があるため、の中にマージする必要があることに注意してください。
XML の解析に加えて、XML を生成するにはどうすればよいでしょうか?
-
99% の場合、生成する必要がある XML 構造は非常に単純なので、次のようになります
最简单也是最有效的生成XML的方法是拼接字符串
。L = [] L.append(r'<?xml version="1.0"?>') L.append(r'<root>') L.append(encode('some & data')) L.append(r'</root>') return ''.join(L)
HTMLパーサー
検索エンジンを作成する場合、最初のステップは、クローラーを使用してターゲット Web サイトのページをクロールすることです。2 番目のステップは、HTML ページを解析して、コンテンツがニュース、写真、またはビデオであるかどうかを確認することです。
- 最初のステップが完了したと仮定すると、2 番目のステップでは HTML をどのように解析する必要があるでしょうか。
HTML は本質的には ですXML的子集
が、HTML的语法
XML ほど厳密ではないため、標準を使用してDOM或SAX
HTML を解析することはできません。
Python は、HTMLParser
わずか数行のコードで HTML を解析する非常に便利な方法を提供します。
from html.parser import HTMLParser
from html.entities import name2codepoint
class MyHTMLParser(HTMLParser):
def handle_starttag(self, tag, attrs):
print('<%s>' % tag)
def handle_endtag(self, tag):
print('</%s>' % tag)
def handle_startendtag(self, tag, attrs):
print('<%s/>' % tag)
def handle_data(self, data):
print(data)
def handle_comment(self, data):
print('<!--', data, '-->')
def handle_entityref(self, name):
print('&%s;' % name)
def handle_charref(self, name):
print('&#%s;' % name)
parser = MyHTMLParser()
parser.feed('''<html>
<head></head>
<body>
<!-- test html parser -->
<p>Some <a href=\"#\">html</a> HTML tutorial...<br>END</p>
</body></html>''')
-
feed() メソッドを使用できます
多次调用
。つまり、HTML 文字列全体を一度に挿入する必要はなく、部分ごとに挿入できます。 -
特殊文字には英語で表現される文字と数字で表現される文字の 2 種類があり的Ӓ
、どちらの文字もParser
解析できます。
ランダム
Python のランダム モジュールは主に乱数を生成するために使用されます。さまざまなディストリビューション用に擬似乱数ジェネレーターを実装しました。
一般的な方法
andom() 生成一个 [0.0, 1.0) 之间的随机小数
seed(seed) 初始化给定的随机数种子
randint(a, b) 生成一个 [a, b] 之间的随机整数
uniform(a, b) 生成一个 [a, b] 之间的随机小数
choice(seq) 从序列 seq 中随机选择一个元素
shuffle(seq) 将序列 seq 中元素随机排列, 返回打乱后的序列
ランダム.ランダム()
import random
print(random.random())
#0.4784904215869241
**ランダム.シード(シード) **
-
指定された乱数シードを初期化します
-
コンピューターは決定論的アルゴリズムを使用して、一連の乱数を計算します。コンピュータによって生成される乱数は、真の意味でランダムではありません
但具有类似于随机数的统计特征,如均匀性、独立性等
。 -
コンピュータは に基づいており
随机数种子产生随机数序列,如果随机数种子相同,每次产生的随机数序列是相同的
、乱数シードが異なれば、生成される乱数列も異なります。random.seed(10) a = random.randint(0, 100) print(a) a = random.randint(0, 100) print(a) a = random.randint(0, 100) print(a) # 73 # 4 # 54 random.seed(10) a = random.randint(0, 100) print(a) a = random.randint(0, 100) print(a) a = random.randint(0, 100) print(a) # 73 # 4 # 54
- 結果
第1个random.seed(10)设定种子为 10 产生第 1 个随机数 73 产生第 2 个随机数 4 产生第 3 个随机数 54 第2个random.seed(10)设定种子为 10 产生第 1 个随机数 73 产生第 2 个随机数 4 产生第 3 个随机数 54 可以看出,当种子相同时,产生的随机数序列是相同的
ランダム.randint(a, b)
-
[a, b] の間のランダムな整数を生成します。例は次のとおりです。
a = random.randint(0, 2) print(a) a = random.randint(0, 2) print(a) a = random.randint(0, 2) print(a) # 1 # 2 # 0
ランダム.ユニフォーム(a, b)
- [a, b] の間でランダムな小数を生成することです
import random random.uniform(0, 2) #0.20000054219225438 random.uniform(0, 2) #1.4472780206791538 random.uniform(0, 2) #0.5927807855738692
ランダム選択(シーケンス)
-
シーケンス seq から要素をランダムに選択します
import random seq = [1, 2, 3, 4] random.choice(seq) #3 random.choice(seq) #1
ランダムシャッフル(シーケンス)
-
シーケンス seq 内の要素をランダムに配置し、スクランブルされたシーケンスを返します。
import random seq = [1, 2, 3, 4] random.shuffle(seq) #[1, 3, 2, 4]
まとめ
- HTMLParser を使用すると、Web ページのコンテンツを解析できます
文本、图像
。