Обработка разбиения на страницы и динамического содержимого
Переход по ссылкам на следующую страницу и использование Playwright для страниц, отображаемых с помощью JavaScript.
«Обработка разбиения на страницы и динамического содержимого» — бесплатный урок AI Agents на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Agents, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Agents содержит 4 уроков всего.
Проблема пагинации
Большинство реальных веб-сайтов не размещают все данные на одной странице. Результаты распределяются по нескольким страницам, чтобы снизить нагрузку. Агент должен обнаруживать пагинацию и переходить по страницам, чтобы собрать полный набор данных.
Существуют два распространённых способа пагинации: ссылки на следующую страницу и шаблоны адресов с номерами страниц.
Обнаружение ссылок на следующую страницу
На многих сайтах есть кнопка «Далее» или ссылка со стрелкой. Найдите тег ссылки с rel='next' или текстом вроде «Далее», извлеките её href и переходите по ней в цикле, пока такая ссылка не исчезнет.
from bs4 import BeautifulSoup
import httpx
def scrape_all_pages(start_url: str) -> list:
results = []
url = start_url
while url:
response = httpx.get(url, timeout=10.0)
soup = BeautifulSoup(response.text, 'html.parser')
# Collect data from this page
for item in soup.select('.result-item'):
results.append(item.text.strip())
# Find the next page link
next_link = soup.find('a', rel='next') or soup.find('a', string='Next')
url = next_link.get('href') if next_link else None
return resultsШаблоны адресов с номерами страниц
Многие программные интерфейсы и сайты используют предсказуемые шаблоны адресов: /results?page=1, /results?page=2 и т. д. Агент может перебирать такие адреса напрямую, не выполняя поиск ссылки на следующую страницу в DOM.
import httpx
def scrape_paginated_api(base_url: str, max_pages: int = 10) -> list:
all_items = []
for page in range(1, max_pages + 1):
response = httpx.get(
base_url,
params={'page': page, 'per_page': 50},
timeout=10.0
)
response.raise_for_status()
data = response.json()
items = data.get('results', [])
if not items:
break # No more data
all_items.extend(items)
print(f'Page {page}: fetched {len(items)} items')
return all_itemsПагинация на основе курсора
Современные программные интерфейсы, включая GitHub, Slack и Twitter, используют пагинацию на основе курсора. Каждый ответ содержит маркер-курсор для следующей страницы. Передавайте этот маркер в следующем запросе, пока он не исчезнет или не станет нулевым.
import httpx
def fetch_with_cursor(url: str, headers: dict) -> list:
all_data = []
cursor = None
while True:
params = {'cursor': cursor} if cursor else {}
response = httpx.get(url, headers=headers, params=params, timeout=10.0)
response.raise_for_status()
data = response.json()
all_data.extend(data.get('items', []))
cursor = data.get('next_cursor') # None when done
if not cursor:
break
return all_dataСтатическое и динамическое содержимое
Некоторые страницы загружают содержимое с помощью JavaScript после передачи исходного HTML. Обычный клиент для веб-запросов получает только пустую оболочку — фактические данные внедряются JS в браузере.
Для таких страниц инструменты вроде Плейрайт запускают настоящий браузерный движок и ждут выполнения JavaScript перед извлечением содержимого.
Установка и импорт Плейрайт
Установите Плейрайт с помощью pip install playwright, затем выполните playwright install chromium, чтобы загрузить браузер. Используйте async_playwright() в асинхронных рабочих процессах агента.
# Installation (run in terminal):
# pip install playwright
# playwright install chromium
from playwright.async_api import async_playwright
import asyncio
async def fetch_dynamic(url: str) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
html = await page.content() # Full rendered HTML
await browser.close()
return html
# html = asyncio.run(fetch_dynamic('https://example.com'))Ожидание загрузки динамического содержимого
Страницы JavaScript часто загружают данные асинхронно. Укажите Плейрайт, чтобы он ждал появления определённого элемента перед извлечением содержимого. Так Вы убедитесь, что нужные данные действительно присутствуют в DOM.
from playwright.async_api import async_playwright
async def scrape_dynamic_table(url: str) -> list:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
# Wait for the table to appear in the DOM
await page.wait_for_selector('table.results', timeout=10000)
html = await page.content()
await browser.close()
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
return [td.text for td in soup.select('table.results td')]Нажатие и взаимодействие со страницами
Плейрайт может имитировать действия пользователя: нажатия, заполнение форм, прокрутку и ввод с клавиатуры. Это позволяет агенту проходить процессы входа, работать с раскрывающимися списками и перемещаться по страницам с бесконечной прокруткой.
from playwright.async_api import async_playwright
async def click_load_more(url: str) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
# Click the 'Load More' button
load_more = page.locator('button:text("Load More")')
if await load_more.count() > 0:
await load_more.click()
await page.wait_for_timeout(2000) # wait 2s for content
html = await page.content()
await browser.close()
return htmlОбработка бесконечной прокрутки
Некоторые сайты загружают дополнительные данные по мере прокрутки вниз. Плейрайт может имитировать прокрутку, чтобы запускать такую загрузку. Прокручивайте страницу снова и снова и каждый раз проверяйте, появилось ли новое содержимое.
from playwright.async_api import async_playwright
async def scrape_infinite_scroll(url: str, scroll_count: int = 5) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
for _ in range(scroll_count):
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)')
await page.wait_for_timeout(1500) # wait for new content
html = await page.content()
await browser.close()
return htmlОбъединение Плейрайт и BeautifulSoup
После того как Плейрайт отобразит страницу и вернёт полный HTML, передайте его в BeautifulSoup для удобного извлечения данных. Так Вы объедините сильные стороны обеих библиотек.
from playwright.async_api import async_playwright
from bs4 import BeautifulSoup
async def extract_js_rendered_data(url: str) -> list:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
await page.wait_for_selector('.product-card')
html = await page.content()
await browser.close()
soup = BeautifulSoup(html, 'html.parser')
products = []
for card in soup.select('.product-card'):
products.append({
'name': card.select_one('.name').text.strip(),
'price': card.select_one('.price').text.strip()
})
return productsВыбор подходящего инструмента
Плейрайт нужен не для каждой страницы. Используйте самый простой рабочий подход:
- Статический HTML: клиент для веб-запросов + BeautifulSoup (быстро, без затрат на запуск браузера)
- Программный интерфейс в формате JSON с пагинацией: клиент для веб-запросов с параметрами страницы или курсора
- Содержимое, отображаемое с помощью JS: асинхронный Плейрайт (медленнее, но мощнее)
Всегда начинайте со статического подхода и обращайтесь к Плейрайт только при необходимости.
Проверка знаний: пагинация и динамическое содержимое
Проверьте, насколько хорошо Вы понимаете обработку пагинации и динамического содержимого.
Итоги: пагинация и динамическое содержимое
Теперь Ваши агенты умеют работать со всеми основными видами веб-содержимого:
- Переходить по ссылкам на следующую страницу или перебирать параметры страниц в адресах
- Использовать маркеры-курсоры для пагинации современных программных интерфейсов
- Использовать
async_playwright()для страниц, отображаемых с помощью JavaScript - Ждать появления элементов с помощью
page.wait_for_selector() - Объединять Плейрайт с BeautifulSoup для удобного извлечения данных
Всегда начинайте с самого простого подхода и переходите к Плейрайт только тогда, когда статический подход не справляется.
Часто задаваемые вопросы
Урок «Обработка разбиения на страницы и динамического содержимого» бесплатный?
Да — полный текст урока «Обработка разбиения на страницы и динамического содержимого» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Agents, подпишись на CoddyKit PRO. Курс AI Agents содержит 4 уроков всего.
Чему я научусь в уроке «Обработка разбиения на страницы и динамического содержимого»?
Переход по ссылкам на следующую страницу и использование Playwright для страниц, отображаемых с помощью JavaScript. Ты практикуешь AI Agents с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать AI Agents?
Предыдущий опыт не требуется. AI Agents на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Обработка разбиения на страницы и динамического содержимого»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке AI Agents?
Да. Каждый урок AI Agents включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- HTTP-клиенты для агентов: httpx и requests
- Разбор HTML с помощью BeautifulSoup
- Обработка разбиения на страницы и динамического содержимого
- Корректные методы веб-скрейпинга