Files
LLM-UI/scraper/forums/phpbb/paginate.py
T
naeel 5c142096de scraper: новая архитектура — core/ + forums/ (BaseAdapter, XenForo, phpBB)
- core/ — общий слой: fetch, throttle, output, state, runner
- forums/base.py — абстрактный BaseAdapter
- forums/xenforo/ — адаптер для XenForo (vwts.ru)
- forums/phpbb/ — адаптер для phpBB (нива-лада.рф)
- __main__.py — точка входа CLI
- history/001-initial-structure.md — журнал изменений

Также на ВМ (не в этом коммите):
- lada_scraper/parse.py — пропуск sticky-тем при многопоточном парсинге
2026-06-06 11:46:57 +04:00

111 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Пагинация phpBB.
phpBB использует параметр ?start=N для пагинации, где:
N = (page - 1) * items_per_page
Страницы раздела:
viewforum.php?f=22&start=25 ← страница 2
viewforum.php?f=22&start=50 ← страница 3
...
Страницы темы:
viewtopic.php?f=22&t=123&start=10 ← страница 2
viewtopic.php?f=22&t=123&start=20 ← страница 3
...
HTML-структура пагинации:
<ul class="pagination">
<li><a href="./viewforum.php?f=22&start=25">2</a></li>
<li><a href="./viewforum.php?f=22&start=50">3</a></li>
...
<li><a href="./viewforum.php?f=22&start=1800">72</a></li>
</ul>
"""
import re
import logging
from bs4 import BeautifulSoup
log = logging.getLogger(__name__)
def count_pages(soup: BeautifulSoup, per_page: int) -> int:
"""Определить количество страниц в пагинации phpBB.
Алгоритм:
1. Ищем ul.pagination (или ul.page-nav).
2. Собираем все start=N из href.
3. Находим max_start.
4. Вычисляем: pages = max_start / per_page + 1.
Args:
soup: BeautifulSoup страницы раздела или темы.
per_page: Количество элементов на странице (темы=25, посты=10).
Returns:
int: количество страниц (минимум 1).
"""
# Ищем контейнер пагинации (два варианта класса)
nav = soup.find("ul", class_="pagination")
if nav is None:
nav = soup.find("ul", class_="page-nav")
if nav is None:
return 1
# Собираем все start=N из ссылок
starts = set()
for link in nav.select("a"):
href = link.get("href", "")
match = re.search(r"[?&]start=(\d+)", href)
if match:
starts.add(int(match.group(1)))
if not starts:
return 1
max_start = max(starts)
pages = (max_start // per_page) + 1
return pages
def page_url(base_url: str, page_num: int, per_page: int) -> str:
"""Сформировать URL страницы раздела phpBB.
Формат:
page=1 → base_url (без ?start=)
page>1 → base_url + &start=N
Args:
base_url: URL страницы без параметра start (напр. viewforum.php?f=22).
page_num: Номер страницы (1-based).
per_page: Количество элементов на страницу.
Returns:
str: URL страницы с ?start= (если page>1).
"""
if page_num <= 1:
return base_url
start = (page_num - 1) * per_page
separator = "&" if "?" in base_url else "?"
return f"{base_url}{separator}start={start}"
def topic_page_url(topic_url: str, page_num: int, per_page: int) -> str:
"""Сформировать URL страницы темы phpBB.
Args:
topic_url: Полный URL темы.
page_num: Номер страницы (1-based, начиная с 2).
per_page: Количество постов на страницу.
Returns:
str: URL страницы темы с ?start=.
"""
if page_num <= 1:
return topic_url
start = (page_num - 1) * per_page
separator = "&" if "?" in topic_url else "?"
return f"{topic_url}{separator}start={start}"