Сегодня занят, давайте попьем воды
Приведенный ниже код взят изэто видеоКак уже упоминалось, ссылка на github:GitHub.com/Мик С уважением…
Первый код выглядит следующим образом: это обычный обходчик цикла for.исходный адрес.
import requests
import bs4
from colorama import Fore
def main():
get_title_range()
print("Done.")
def get_html(episode_number: int) -> str:
print(Fore.YELLOW + f"Getting HTML for episode {episode_number}", flush=True)
url = f'https://talkpython.fm/{episode_number}'
resp = requests.get(url)
resp.raise_for_status()
return resp.text
def get_title(html: str, episode_number: int) -> str:
print(Fore.CYAN + f"Getting TITLE for episode {episode_number}", flush=True)
soup = bs4.BeautifulSoup(html, 'html.parser')
header = soup.select_one('h1')
if not header:
return "MISSING"
return header.text.strip()
def get_title_range():
# Please keep this range pretty small to not DDoS my site. ;)
for n in range(185, 200):
html = get_html(n)
title = get_title(html, n)
print(Fore.WHITE + f"Title found: {title}", flush=True)
if __name__ == '__main__':
main()
Этот код выполнялся 37 секунд, а затем мы использовали инструмент профилировщика pycharm, чтобы увидеть, где это заняло больше времени.
нажмитеProfile (文件名称)
После этого получается подробная взаимосвязь вызовов функций и график затрат времени:
можно увидетьget_html
Этот метод занял 96,7% времени. Время ввода-вывода этой программы достигло 97%.При получении html программа некоторое время ждет там. Это сэкономило бы много времени, если бы мы могли заставить его не просто сидеть и глупо ждать завершения IO, а начать делать что-то еще значимое.
Сделай небольшой расчет, попробуйasyncio
Насколько асинхронная выборка может сократить время?
get_html
Этот метод требует времени36.8s
, всего звонков15
раз, указывая на то, что время, необходимое для фактического получения HTML-кода ссылки, составляет36.8s / 15
= 2.4s
. ** Если он полностью асинхронный, время получения 15 ссылок по-прежнему составляет 2,4 с. ** затем добавьтеget_title
Время работы этой функции0.6s
, поэтому мы оцениваем, что улучшенная программа сможет использовать3s
На выполнение уходит примерно 13 раз времени, то есть производительность можно улучшить в 13 раз.
Взгляните на улучшенный код еще раз.исходный адрес.
import asyncio
from asyncio import AbstractEventLoop
import aiohttp
import requests
import bs4
from colorama import Fore
def main():
# Create loop
loop = asyncio.get_event_loop()
loop.run_until_complete(get_title_range(loop))
print("Done.")
async def get_html(episode_number: int) -> str:
print(Fore.YELLOW + f"Getting HTML for episode {episode_number}", flush=True)
# Make this async with aiohttp's ClientSession
url = f'https://talkpython.fm/{episode_number}'
# resp = await requests.get(url)
# resp.raise_for_status()
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
resp.raise_for_status()
html = await resp.text()
return html
def get_title(html: str, episode_number: int) -> str:
print(Fore.CYAN + f"Getting TITLE for episode {episode_number}", flush=True)
soup = bs4.BeautifulSoup(html, 'html.parser')
header = soup.select_one('h1')
if not header:
return "MISSING"
return header.text.strip()
async def get_title_range(loop: AbstractEventLoop):
# Please keep this range pretty small to not DDoS my site. ;)
tasks = []
for n in range(190, 200):
tasks.append((loop.create_task(get_html(n)), n))
for task, n in tasks:
html = await task
title = get_title(html, n)
print(Fore.WHITE + f"Title found: {title}", flush=True)
if __name__ == '__main__':
main()
Те же шаги создают график профиля:
Видно, что текущее время составляет около 3,8 с, что в основном соответствует нашим ожиданиям.
Мой официальный аккаунт: Полный стек не существует