This commit is contained in:
114
parsers/universal.py
Normal file
114
parsers/universal.py
Normal file
@@ -0,0 +1,114 @@
|
||||
"""
|
||||
Парсер любого источника - универсальный парсер
|
||||
"""
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from datetime import datetime
|
||||
from newspaper import Article
|
||||
from urllib.parse import urljoin, urlparse, urldefrag
|
||||
from typing import Set
|
||||
|
||||
from .base import BaseParser
|
||||
from utils import logger
|
||||
from services import gpt_response_message, update_bd_and_create_document
|
||||
import work_parser as wp
|
||||
|
||||
|
||||
def check_url(url: str) -> bool:
|
||||
"""
|
||||
Проверяет, существует ли URL в базе данных
|
||||
"""
|
||||
try:
|
||||
response = wp.check_url_exists(url)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print(result["exists"])
|
||||
return result["exists"]
|
||||
else:
|
||||
return False
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
class UniversalParser(BaseParser):
|
||||
"""
|
||||
Универсальный парсер для любого источника
|
||||
"""
|
||||
|
||||
def __init__(self, url: str, promt: str):
|
||||
super().__init__("universal")
|
||||
self.url = url
|
||||
self.promt = promt
|
||||
|
||||
def parse(self) -> None:
|
||||
"""
|
||||
Основной метод парсинга любого источника
|
||||
"""
|
||||
print(f"Начало парсинга: {self.url} с промтом: {self.promt}")
|
||||
self.start_task(self.url)
|
||||
|
||||
try:
|
||||
response = requests.get(self.url)
|
||||
print(response.text)
|
||||
response.raise_for_status()
|
||||
except requests.RequestException:
|
||||
print(f"Ошибка при запросе к {self.url}")
|
||||
self.fail_task()
|
||||
return
|
||||
|
||||
soup = BeautifulSoup(response.text, 'html.parser')
|
||||
base_domain = urlparse(self.url).netloc
|
||||
print(base_domain)
|
||||
|
||||
for a_tag in soup.find_all('a', href=True):
|
||||
href = a_tag['href'].strip()
|
||||
if not href or href.startswith('mailto:') or href.startswith('javascript:'):
|
||||
continue
|
||||
|
||||
# Приведение к абсолютному URL и удаление якорей (#...)
|
||||
abs_url = urljoin(self.url, href)
|
||||
abs_url, _ = urldefrag(abs_url)
|
||||
parsed = urlparse(abs_url)
|
||||
|
||||
# Фильтр: ссылка должна быть на тот же домен
|
||||
if parsed.netloc != base_domain:
|
||||
continue
|
||||
|
||||
print("URL:", abs_url)
|
||||
|
||||
if not check_url(abs_url) and wp.check_error_url(abs_url):
|
||||
try:
|
||||
article = Article(abs_url)
|
||||
article.download()
|
||||
article.parse()
|
||||
|
||||
if len(article.text) > 200 and article.publish_date:
|
||||
time_text = article.publish_date.strftime("%Y/%m/%d %H:%M:%S")
|
||||
|
||||
response_text = gpt_response_message(str(article.text), self.promt)
|
||||
print(response_text)
|
||||
if response_text:
|
||||
update_bd_and_create_document(
|
||||
response_text=response_text,
|
||||
article_date=time_text,
|
||||
url=abs_url,
|
||||
parsed_at=str(datetime.now()),
|
||||
original_text=article.text,
|
||||
other=self.promt
|
||||
)
|
||||
else:
|
||||
wp.add_error_url(self.url, abs_url)
|
||||
except Exception as e:
|
||||
print(f"Ошибка при обработке статьи {abs_url}: {e}")
|
||||
logger.info(f"Ошибка при обработке статьи {abs_url}: {e}")
|
||||
continue
|
||||
|
||||
self.complete_task()
|
||||
|
||||
|
||||
def start_pars_all_istochnik(url: str, promt: str) -> None:
|
||||
"""
|
||||
Точка входа для парсинга любого источника
|
||||
"""
|
||||
parser = UniversalParser(url, promt)
|
||||
parser.parse()
|
||||
Reference in New Issue
Block a user