Python クローラー: クローラーの効率を向上させる非同期の方法
Python マルチスレッド構文
最初の方法
from threading import Thread
t = Thread(target=fuc)
t.start() #多线程状态可以为开始工作状态,具体执行时间由CPU决定
別の方法
class MyThread(Thread):
def run(self):
XXXXXX
t = MyThread()
t.start()
Python マルチプロセス構文 (一般的には使用されません)
from multiprocessing import Process
p = Process(tarfet=func)
p.start()
スレッドプールとプロセスプール
スレッド プール: 一度にいくつかのスレッドを開き、ユーザーがタスクをスレッド プールに直接送信すると、スレッド タスクのスケジューリングがスレッド プールに渡されて完了します。
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
with ThreadPoolExecutor(50) as t:
for i in range(100):
t.submit(fn,name=XXXX)
例: スレッド プールを使用して郵便教育データ情報をクロールする
アイデア:
1. 1 ページ分のデータを抽出する
2. スレッド プールを使用して複数のページを同時にクロールする
コード:
import requests
from lxml import etree
import csv
import time
from concurrent.futures import ThreadPoolExecutor
f = open("book2.csv",mode="w",newline='')
csvwriter = csv.writer(f)
def download_one_page(url):
resp = requests.get(url)
# print(resp.text)
html = etree.HTML(resp.text)
divs = html.xpath("/html/body/div[3]/div/div/div/div/ul/li/div[2]")
for div in divs:
name = div.xpath("./h4/a/text()")[0]
# print(name)
author = div.xpath("./div/span/text()")[0].strip()
# print(author)
price = div.xpath("./span/span/text()")[0].strip("¥")
# print(price)
csvwriter.writerow([name, author, price])
time.sleep(1)
resp.close()
if __name__ == '__main__':
with ThreadPoolExecutor(50) as t:
for i in range(0,38):
t.submit(download_one_page,f"https://www.ryjiaoyu.com/tag/details/7/?page={i}")
print("over!")
f.close()
コルーチン
コルーチン: プログラムが IO 操作に遭遇すると、他のタスクに選択的に切り替えることができます。
Python はコルーチンを記述します
import asyncio
async def func1():
XXXX
async def fucn2():
XXXX
async def fucn3():
XXXX
async def main():
# g = func() #此时函数是异步协程函数,此时函数执行得到的是一个协程对象
tasks = [
asyncio.create_task(func1())
asyncio.create_task(func2())
asyncio.create_task(func3())
]
await asyncio.wait(tasks)
if __name__ == '__main__':
asyncio.run(main())
非同期操作のスリープ
await asyncio.sleep(3) #异步操作时的代码
爬虫類への応用
async def download(url):
print("loading")
## 异步操作的网络请求
print("over")
async def main():
urls = [
"XXXX",
"XXXX",
“XXXXX"
]
tasks = []
for url in urls:
d = download(url)
tasks.append(d)
await asyncio.wait(tasks)
if __name__ == '__main__':
asyncio.run(main())
非同期操作のネットワーク リクエスト
インストール
pip install aiohttp
Python はネットワーク リクエストを書き込みます
import asyncio
import aiohttp
urls = [
"XXXXX"
"XXXXX"
"XXXXX"
]
async def aiodownload(url):
async with aiohttp.ClientSession() as session:
# session.get() <==> requests.get()
# session.post()<==> requests.post()
async with session.get(url) as resp:
resp.text()
# 写入文件
with open(name,mode="wb") as f:
f.write(await resp.content.read()) #读取的是异步内容,需要await挂起
async def main():
tasks = []
for url in urls:
tasks.append(aiodownload(url))
await asyncio.wait(tasks)
if __name__ == '__main__':
asyncio.run(main())