lada_scraper: парсер phpBB форума нива-лада.рф + доку
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
"""Пагинация phpBB.
|
||||
|
||||
phpBB: пагинация через параметр start=N, где N = (page-1) * items_per_page.
|
||||
|
||||
На странице раздела:
|
||||
<a href="./viewforum.php?f=22&start=25">2</a>
|
||||
<a href="./viewforum.php?f=22&start=50">3</a>
|
||||
...
|
||||
<a href="./viewforum.php?f=22&start=1800">72</a>
|
||||
|
||||
На странице темы:
|
||||
<a href="./viewtopic.php?f=22&t=123&start=10">2</a>
|
||||
...
|
||||
"""
|
||||
|
||||
import re, logging
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def count(soup: BeautifulSoup) -> int:
|
||||
"""Сколько страниц в пагинации. Если нет — 1."""
|
||||
for cls in ("pagination", "page-nav"):
|
||||
nav = soup.find("ul", class_=cls)
|
||||
if nav:
|
||||
break
|
||||
else:
|
||||
return 1
|
||||
|
||||
nums = set()
|
||||
for a in nav.select("a"):
|
||||
href = a.get("href", "")
|
||||
text = a.text.strip()
|
||||
|
||||
# start=N из href
|
||||
m = re.search(r"[?&]start=(\d+)", href)
|
||||
if m:
|
||||
per_page = int(m.group(1))
|
||||
# Определяем items_per_page по первому start
|
||||
if hasattr(count, "_per_page"):
|
||||
pass
|
||||
nums.add(per_page)
|
||||
|
||||
# Числовой текст ссылки
|
||||
try:
|
||||
nums.add(int(text))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if not nums:
|
||||
return 1
|
||||
|
||||
# Находим максимальный номер страницы из текста ссылок
|
||||
max_page_num = max((int(a.text.strip()) for a in nav.select("a")
|
||||
if a.text.strip().isdigit()), default=1)
|
||||
|
||||
# Находим max start
|
||||
max_start = max(nums)
|
||||
|
||||
# Определяем per_page из наименьшего start > 0
|
||||
positive_starts = [s for s in nums if s > 0]
|
||||
if positive_starts:
|
||||
per_page = min(positive_starts)
|
||||
else:
|
||||
# Не можем определить — возвращаем по тексту ссылок
|
||||
return max_page_num
|
||||
|
||||
# Вычисляем: страниц = (max_start / per_page) + 1
|
||||
pages = (max_start // per_page) + 1
|
||||
return pages
|
||||
|
||||
|
||||
def page_url(base_url: str, page: int, per_page: int) -> str:
|
||||
"""Сформировать URL для страницы пагинации.
|
||||
|
||||
Args:
|
||||
base_url: URL без start= (напр. viewforum.php?f=22)
|
||||
page: номер страницы (1-based)
|
||||
per_page: элементов на странице
|
||||
"""
|
||||
if page <= 1:
|
||||
return base_url
|
||||
start = (page - 1) * per_page
|
||||
sep = "&" if "?" in base_url else "?"
|
||||
return f"{base_url}{sep}start={start}"
|
||||
Reference in New Issue
Block a user