正規表現
一般的なメタキャラクター
. は改行を除く任意の文字に一致します
\w はサブタイトル、数字、アンダースコアと一致します
\s は任意の空白文字に一致します
\d は数字と一致します
\n は改行文字と一致します
\t はタブ文字と一致します
^ 匹配字符串的开始 # 开发常用
$ 匹配字符串的结尾
\W は英数字以外またはアンダースコアと一致します
\D は数字以外に一致します
\S は空白以外の文字に一致します
a|b は文字 a または b と一致します
() は括弧で囲まれた式と一致し、グループを示します
[…] 文字グループ内の文字と一致します
[^…] は文字グループ内の文字を除くすべての文字に一致します。**[ ] の ^** は「not」を意味します
数量詞
* 重复0次或更多次
+ 重复1次或更多次
? 重复0次或1次
{
n} 重复n次
{
n,} 重复n次或更多次
{
n,m}重复n到m次
貪欲なマッチング、クローラーによってよく使用されます
.* 贪婪匹配
.*? 惰性匹配,尽可能间隔少的匹配
Python-re
import re
# findall:匹配字符串中所有正则内容
lst = re.findall(r"\d+", "我的电话是10086,我孩子的电话是10010")
print(lst)
['10086', '10010']
# finditer:匹配字符串中所有的内容【返回是迭代器】,从迭代器中拿到内容需要.group()
# 最常用,效率高
it = re.finditer(r"\d+", "我的电话是10086,我孩子的电话是10010")
for i in it:
print(i.group())
10086
10010
# search:返回的是match对象,拿数据需要.group()
# 找到一个结果就返回,不找了
# 常用
s = re.search(r"\d+", "我的电话是10086,我孩子的电话是10010")
print(s.group())
10086
# match:从头匹配,拿数据需要.group()
s = re.match(r"\d+", "10000我的电话是10086,我孩子的电话是10010")
print(s.group())
10000
# 预加载正则,后面没有r''
obj = re.compile(r"\d+")
ret = obj.finditer("我的电话是10086,我孩子的电话是10010")
for j in ret:
print(j.group())
# 可以反复用
bhq = obj.findall("疑是银河落九天,为啥不还10000000")
print(bhq)
10086
10010
['10000000']
s = """
<div class='red'><span id='1'>西游记</span></div>
<div class='green'><span id='2'>三国演义</span></div>
<div class='blue'><span id='3'>水浒</span></div>
<div class='yellow'><span id='4'>红楼666</span></div>
"""
obj = re.compile(r"<div class='.*?'><span id='\d+'>.*?</span></div>", re.S)
obj2 = re.compile(r"<div class='.*?'><span id='\d+'>(?P<wahaha>.*?)</span></div>", re.S)
# re.S 让.能匹配换行符
# (?P<分组名字>正则) 可以从正则匹配的内容中提取一部分
result = obj2.finditer(s)
for it in result:
print(it.group("wahaha"))
演技
# 设置代理
proxies = {
"https": "https://210.60.8.83:3129"
}
# 添加代理
resp = requests.get("https://www.baidu.com", proxies =proxies)
resp.encoding = 'utf-8'
print(resp.text)
マルチスレッド化
プロセス - リソースユニット
スレッド - 実行単位
各プロセスに少なくとも 1 つのスレッドがあり、プログラムを開始します。デフォルトでメインスレッドがあります。
方法 1:
from threading import Thread
def func():
for i in range(1000):
print("func", i)
if __name__ == '__main__':
t = Thread(target=func) # 目标线程
t.start() # 多线程状态为开始工作状态,具体执行时间由cpu决定
for i in range(1000):
print("main", i)
# 传参
def func(name):
for i in range(1000):
print(name, i)
if __name__ == '__main__':
t = Thread(target=func, args=("周杰伦",)) # 目标线程,,args参数必须是 元组 传参
t.start() # 多线程状态为开始工作状态,具体执行时间由cpu决定
for i in range(1000):
print("main", i)
方法 2:
# 传参时,定义构造函数,def __init__(self):
class myThread(Thread):
def run(self):
for i in range(1000): # 固定的 - > 当线程被执行的时候,被执行的就是run()
print("子线程", i)
if __name__ == '__main__':
t = myThread()
# t.run() # 此为方法的调用 - >仍然单线程进行
t.start() # 开启线程
for i in range(1000):
print("主线程", i)
# 多进程使用,创建多进程资源远远大于多线程
# 写法跟线程一模一样,降低开发者记忆成本,资源使用完全不一样
from multiprocessing import Process
def func():
for i in range(1000):
print("func", i)
if __name__ == '__main__':
p = Process(target=func) # 目标线程
p.start() # 多线程状态为开始工作状态,具体执行时间由cpu决定
for i in range(1000):
print("main", i)
スレッドプール
一般的な考え方は、最初に 1 つの実装を作成し、それをスレッド プールに入れることです。
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def func(name):
for i in range(1000):
print(name, i)
if __name__ == '__main__':
# 创建线程池
with ThreadPoolExecutor(50) as t:
for i in range(100):
# t.submit(func, name=f"线程-{i}")
t.submit(func, name="changjiang")
# 等待线程池中的任务全部执行完毕,才能继续执行(守护)
print(123)
コルーチン
プログラムが IO 動作中にスレッドがブロックされ、CPU が機能しません
例: input()、sleep()、request.get() など。
コルーチン: プログラムが IO 操作を予測すると、他のタスクに切り替えることを選択できます。これは私にとってはうまくいきました。CPUをプログラムに結び付ける
ミクロレベルでは、これはタスクごとの切り替えであり、切り替え条件は一般に IO 操作です。
マクロレベルでは、複数のタスクが実際に一緒に実行され、マルチタスクの非同期操作が行われていることがわかります。
# @desc : 写爬虫的模板,协程应用,效率极高,相当于单线程
import asyncio
async def download(url):
print("准备开始下载")
await asyncio.sleep(2) # 网络请求; # requests.get() 是不行的
print("下载完成")
async def main():
urls = [
"http://www.baidu/com",
"http://www.bilibili.com",
"http://www.163.com"
]
tasks = []
for url in urls:
# d = download(url) # python3.11之后会被干掉
d = asyncio.create_task(download(url)) # python3.8之后的写法
tasks.append(d)
await asyncio.wait(tasks)
if __name__ == '__main__':
asyncio.run(main())
クローラービデオ処理
一般的な動画サイトはどうなっているのでしょうか?
ユーザーアップロード -> トランスコーディング (ビデオを 2k、1080、SD に作成) -> スライス処理 (個々のファイルを分割) 60
ユーザーがプログレスバーを引っ張っているときの処理方法
==================
記録するファイルが必要です: 1. ビデオ再生シーケンス。2. ビデオが保存されるパス。
M3U8 txt json => テキスト
ビデオを取得するには:
m3u8 を見つける (さまざまな方法で)
m3u8経由でtsファイルにダウンロード
ts ファイルは、さまざまな手段 (プログラミング手段に限定されない) で 1 つの mp4 ファイルに結合できます。