В тази статия ще се гмурнем в дълбоките води на уеб скрапинга и по-конкретно – как да извличаме данни от множество уеб страници бързо и ефективно чрез асинхронно програмиране. Ще използваме популярната библиотека aiohttp за извършване на HTTP заявки и библиотеката BeautifulSoup за обработка на HTML съдържанието.

Какво е уеб скрапинг?

Уеб скрапингът е процесът на автоматизирано извличане на данни от уеб сайтове. Вместо ръчно да копираме информация от уеб страници, можем да напишем програма, която да навигира през сайта и да извлича нужните ни данни, спестявайки много време и усилия.

Някои типични приложения на уеб скрапинга включват:

  • Събиране на цени и продуктова информация от онлайн магазини;
  • Извличане на отзиви и коментари от платформи като Amazon или Yelp;
  • Следене на новинарски сайтове и блогове за ключови думи;
  • Автоматизиране на попълването на онлайн формуляри и въвеждане на данни.

Въпреки че уеб скрапингът може да бъде изключително полезен, важно е винаги да се съобразяваме с правилата и условията за ползване на сайтовете, от които извличаме данни. Някои сайтове изрично забраняват автоматизираното извличане на съдържание, така че винаги проверявайте правилата преди да започнете.

Асинхронни HTTP заявки с aiohttp

Една от основните стъпки в процеса на уеб скрапинг е изпращането на HTTP заявки към уеб сървъра и получаването на отговори с HTML съдържание, което след това да обработим. Библиотеката aiohttp предоставя удобен и ефективен начин за асинхронна работа с HTTP в Python.

Нека видим как можем да използваме aiohttp за изпращане на множество заявки едновременно:


import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        'https://python.org',
        'https://wikipedia.org',
        'https://github.com'
    ]

    async with aiohttp.ClientSession() as session:
        tasks = []
        for url in urls:
            task = asyncio.create_task(fetch(session, url))
            tasks.append(task)

        pages = await asyncio.gather(*tasks)
        print(f"Fetched {len(pages)} pages")

asyncio.run(main())

В този пример дефинираме асинхронна функция fetch, която приема aiohttp.ClientSession и URL, и връща съдържанието на отговора като текст. В основната функция main създаваме списък с URL адреси, които искаме да „скрейпнем“.

След това създаваме нова aiohttp.ClientSession и итерираме през списъка с URL адреси. За всеки URL създаваме нова асинхронна задача fetch и я добавяме към списъка tasks.

Накрая използваме asyncio.gather, за да изпълним всички задачи едновременно и изчакваме резултата – списък от съдържанията на всички уеб страници.

Обработка на HTML с BeautifulSoup

След като веднъж сме получили HTML на дадена уеб страница, можем да използваме библиотеката BeautifulSoup за лесно извличане на нужните ни данни от него. BeautifulSoup ни позволява да търсим елементи по тагове, класове, идентификатори и всякакви други атрибути.

Ето пример как можем да извлечем всички заглавия от уеб страницата на Python:


from bs4 import BeautifulSoup

async def parse_page(html):
    soup = BeautifulSoup(html, 'html.parser')
    titles = [title.text for title in soup.find_all('h1')]
    print(f"Found {len(titles)} titles:")
    print(titles)

# Let's add parse_page in main function
pages = await asyncio.gather(*tasks)
for page in pages:
    await parse_page(page)

Тук дефинираме асинхронна функция parse_page, която приема HTML като текст и го обработва с BeautifulSoup. Използваме find_all, за да намерим всички елементи <h1> и извлечем текстовото им съдържание в списък titles.

След това извикваме parse_page за всяка заредена уеб страница в главната ни функция.

BeautifulSoup поддържа много по-сложни заявки за търсене, като използване на CSS селектори, регулярни изрази, търсене на родителски и дъщерни елементи и т.н. Можете да научите повече в официалната документация.

Съвети и добри практики

  • Винаги зачитайте правилата за robots.txt и ограниченията за достъп на сайтовете, които скрейпвате;
  • Не правете твърде много заявки за кратък период от време, за да избегнете блокирането от сайта. Добавете разумен интервал между заявките;
  • Кеширайте резултатите локално, за да избегнете ненужно претоварване на сайтовете с повтарящи се заявки;
  • Използвайте User-Agent стринг, който ясно се идентифицира като бот, за да може собствениците на сайтове да ви контактуват при нужда;
  • Ако даден сайт предоставя API, използвайте го вместо да скрейпвате – така ще получите данните в структуриран формат и ще намалите натоварването на сървъра.

Надявам се тази статия да ви е дала солидна основа, от която да започнете вашите уеб скрапинг проекти с Python. Възможностите са безкрайни – от следене на цени и автоматизиране на онлайн задачи до извличане на големи количества данни за анализ и машинно обучение.

Не забравяйте винаги да скрейпвате отговорно и да уважавате сайтовете и собствениците им. Със силата идва и отговорността!

Categorized in:

Уеб скрапинг,

Last Update: май 3, 2024