CoderCastrov logo
CoderCastrov
Парсер данных

Beautiful Soup: Сравнение подходов к парсингу веб-страниц с использованием многопоточности, многопроцессорности и асинхронности

Beautiful Soup: Сравнение подходов к парсингу веб-страниц с использованием многопоточности, многопроцессорности и асинхронности
просмотров
3 мин чтение
#Парсер данных
Table Of Content

Исследование многопроцессорности, многопоточности и asyncio

Мы исследуем преимущества параллельной обработки и проведем подробное сравнение между отсутствием параллельной обработки, многопроцессорностью, многопоточностью и asyncio при использовании Beautiful Soup.

Так же, как и в нашем предыдущем подходе с использованием Selenium, мы продолжим извлекать данные с первых десяти страниц веб-сайта https://quotes.toscrape.com/.

Selenium: Сравнение подходов к параллелизму

Исследование многопроцессорности, многопоточности и асинхронности

medium.com

Давайте создадим список URL-адресов.

url_list = [f"https://quotes.toscrape.com/page/{x}/" for x in range(2,11)]
url_list.insert(0,"https://quotes.toscrape.com/")

Мы можем извлечь тексты цитат, используя атрибут класса text.

<span class="text" itemprop="text">“Мир, который мы создали, является процессом нашей мысли. Его нельзя изменить, не изменив наше мышление.”</span>

С помощью цикла for мы извлекаем тексты по одному, используя библиотеки requests и bs4.

import requests
from bs4 import BeautifulSoup
from datetime import datetime

url_list = [f"https://quotes.toscrape.com/page/{x}/" for x in range(2,11)]
url_list.insert(0,"https://quotes.toscrape.com/")

start = datetime.now()
for url in url_list:
    response = requests.get(url)
    html_content = response.content

    soup = BeautifulSoup(html_content, "html.parser")

    text_elements = soup.find_all(class_="text")

    for element in text_elements:
        text = element.text
        print(text)
        print()

print("Total Time: ", datetime.now()-start)

"""Total Time:  0:00:07.045733"""

Теперь давайте воспользуемся многопроцессорностью.

import requests
from bs4 import BeautifulSoup
from datetime import datetime
from multiprocessing import Pool

url_list = [f"https://quotes.toscrape.com/page/{x}/" for x in range(2,11)]
url_list.insert(0,"https://quotes.toscrape.com/")

def scrape_url(url):
    response = requests.get(url)
    html_content = response.content

    soup = BeautifulSoup(html_content, "html.parser")

    text_elements = soup.find_all(class_="text")

    for element in text_elements:
        text = element.text
        print(text)
        print()

if __name__ == "__main__":

    start = datetime.now()
    with Pool(processes=5) as pool:
        pool.map(scrape_url, url_list)
    print("Total Time: ", datetime.now()-start)

"""Total Time:  0:00:01.563374"""

Впечатляющий результат! Действительно, многопроцессорность лучше всего подходит для задач, которые сильно зависят от процессора. Следовательно, давайте воспользуемся многопоточностью в качестве альтернативы многопроцессорности.

import requests
import threading
from bs4 import BeautifulSoup
from datetime import datetime

url_list = [f"https://quotes.toscrape.com/page/{x}/" for x in range(2,11)]
url_list.insert(0,"https://quotes.toscrape.com/")

def scrape_url(url):
    response = requests.get(url)
    html_content = response.content

    soup = BeautifulSoup(html_content, "html.parser")

    text_elements = soup.find_all(class_="text")

    for element in text_elements:
        text = element.text
        print(text)
        print()

if __name__ == "__main__":

    start = datetime.now()
    threads = []

    for url in url_list:
        thread = threading.Thread(target=scrape_url, args=(url,))
        thread.start()
        threads.append(thread)

    # Wait for all threads to complete
    for thread in threads:
        thread.join()
    print("Total Time: ", datetime.now()-start)

"""Total Time:  0:00:01.681818"""

У нас была та же производительность. Кроме того, мы можем использовать асинхронность.

import asyncio
import aiohttp
from bs4 import BeautifulSoup
from datetime import datetime

url_list = [f"https://quotes.toscrape.com/page/{x}/" for x in range(2,11)]
url_list.insert(0,"https://quotes.toscrape.com/")

async def scrape_url(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            html_content = await response.text()

    soup = BeautifulSoup(html_content, "html.parser")
    text_elements = soup.find_all(class_="text")

    for element in text_elements:
        text = element.text
        print(text)
        print()

async def main():
    tasks = [scrape_url(url) for url in url_list]
    await asyncio.gather(*tasks)

if __name__ == "__main__":

    start = datetime.now()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    print("Total Time: ", datetime.now()-start)

"""Total Time:  0:00:00.937387"""

Это еще лучше!

Читать далее

Selenium: Сравнение подходов к параллелизму

Исследование многопоточности, многопроцессорности и асинхронности

medium.com

Введение в библиотеки Python для парсинга веб-страниц: Selenium, BeautifulSoup и Scrapy

Разблокируйте силу Python для парсинга веб-страниц с помощью Selenium, BeautifulSoup и Scrapy

python.plainenglish.io

Представляем Scrapy: мощная библиотека Python для эффективного парсинга веб-страниц

Начните работу с парсингом веб-страниц с использованием Python и Scrapy

awstip.com

Асинхронные представления Django

Простое руководство по улучшению производительности

faun.pub

Параллелизм и параллелизм в Python

Многопоточность, многопроцессорность, асинхронность и ожидание

faun.pub

Тест ANOVA в Python

Код статистического теста ANOVA с использованием Python

towardsdev.com