FantSayHello #1901 вчера в 17:15 Я даже готов скинуться если в сексе будет использован тот самый черенок Цитата Поделиться сообщением Ссылка на сообщение
yellyex #1902 вчера в 17:24 (изменено) Ratio написал 15 минут назад: yellyex написал 21 минуту назад: Ratio написал 22 минуты назад: yellyex написал 39 минут назад: Ratio написал 41 минуту назад: yellyex написал 44 минуты назад: Ratio написал 45 минут назад: yellyex написал 50 минут назад: Son of Anarchy написал 54 минуты назад: винипух>русалоча>черный плащ ну ты и гавноед алё это хохлина же ему рубль нише и всё нахуй сифка на всю жизнь Не понял причину тряски. Он считает тебя инфантильным, социально-депривированным, ограниченным и отстающим в развитии лет на 25 человеком Кто он? Я или он? Мой пост разве можно истолковать двояко ? Я лично не понял тебя. Скажи прямо. Изобрел с помощью нейронки две програмки, для переименовывания файлов и перемещения. Для смартфонов нужно скачать pydroid3 и плагины (они рядом). import os # ==================== НАСТРОЙКИ ==================== # Выберите режим нумерации: # True -> 001, 002, 003 ... (с ведущими нулями) # False -> 1, 2, 3 ... use_leading_zeros = True # измените здесь # Папка, в которой лежат файлы # Раскомментируйте нужную строку, другую закомментируйте # folder = "/storage/EDDF-B3B1/Download/Русалочка" # вариант 1 folder = "/storage/emulated/0/Download/Electro" # вариант 2 # Общая часть имени и расширение base_name = "Electro" extension = ".flac" start_number = 1 # можно начать не с 1, если нужно # =================================================== # Проверка существования папки if not os.path.exists(folder): print(f"Ошибка: папка '{folder}' не существует.") else: try: # Получаем список файлов в папке all_items = os.listdir(folder) files = [f for f in all_items if os.path.isfile(os.path.join(folder, f))] files.sort() if not files: print("В папке нет файлов.") else: count = len(files) print(f"Найдено файлов: {count}") # Если нужны нули, вычисляем необходимую ширину (например, для 120 файлов ширина 3) if use_leading_zeros: width = len(str(count + start_number - 1)) else: width = None for n, old_name in enumerate(files, start=start_number): old_path = os.path.join(folder, old_name) # Формируем новое имя в зависимости от режима if use_leading_zeros: new_name = f"{base_name} {n:0{width}d}{extension}" else: new_name = f"{base_name} {n}{extension}" new_path = os.path.join(folder, new_name) if os.path.exists(new_path): print(f"Пропуск: {new_name} уже существует") else: os.rename(old_path, new_path) print(f"{old_name} -> {new_name}") print("Готово!") except Exception as e: print(f"Ошибка: {e}") import os import shutil # Укажите путь к корневой папке, откуда нужно извлечь файлы root_folder = "/storage/emulated/0/Download/Electro" # Если нужно обрабатывать только файлы определённых расширений, задайте список # Например: allowed_extensions = ['.mkv', '.mp4', '.avi'] # Если оставить None, будут извлечены все файлы allowed_extensions = '.flac' # или ['.mkv', '.mp4'] def collect_files_to_root(root): if not os.path.exists(root): print(f"Ошибка: папка '{root}' не существует.") return # Собираем все файлы из всех подпапок (рекурсивно) all_files = [] for dirpath, dirnames, filenames in os.walk(root): # Пропускаем саму корневую папку, чтобы не перемещать уже находящиеся в ней файлы if dirpath == root: continue for f in filenames: # Фильтр по расширению, если задан if allowed_extensions is not None: ext = os.path.splitext(f)[1].lower() if ext not in allowed_extensions: continue full_path = os.path.join(dirpath, f) all_files.append(full_path) print(f"Найдено файлов для перемещения: {len(all_files)}") # Перемещаем каждый файл в корневую папку, решая конфликты for src in all_files: filename = os.path.basename(src) dst = os.path.join(root, filename) # Если файл с таким именем уже существует, добавляем суффикс if os.path.exists(dst): name, ext = os.path.splitext(filename) counter = 1 while True: new_name = f"{name}_{counter}{ext}" dst = os.path.join(root, new_name) if not os.path.exists(dst): break counter += 1 # Перемещаем файл shutil.move(src, dst) print(f"Перемещён: {src} -> {dst}") # Удаляем пустые подпапки (оставляя корневую) for dirpath, dirnames, filenames in os.walk(root, topdown=False): if dirpath == root: continue try: os.rmdir(dirpath) # удалит только пустую папку print(f"Удалена пустая папка: {dirpath}") except OSError: # Папка не пуста — пропускаем (но по логике все файлы уже перемещены, так что она должна быть пустой) pass print("Готово! Все файлы собраны в корневой папке, пустые подпапки удалены.") if __name__ == "__main__": collect_files_to_root(root_folder) У тебя был секс с женщиной? Нет конечно! Что за глупые вопросы? Может лучше проститутку снимешь ? В проститутке жить нельзя. Ну на крайняк можно найти какую-нибудь сосну, и выстругать Буратино. И её ебать. Естественно из мальчика надо сделать девочку. Будет: Соснатино. Изменено вчера в 17:25 пользователем yellyex Цитата moonfangtopich написал 29.08.2019 в 14:57: У вас недостаточно широкий кругозор, пацаны Я странствия этого еблана видел в покерных топанах, а потом в таверне - это один из самых безумных людей на форуме. Я искренне надеялся, что его зов о помощи останется незамеченным, но нет, нашелся доброволец и вот уже три страницы мы пожинаем плоды Поделиться сообщением Ссылка на сообщение
Qreeq #1903 вчера в 17:34 yellyex написал 48 минут назад: Изобрел с помощью нейронки две програмки, для переименовывания файлов и перемещения Зачем Цитата Поделиться сообщением Ссылка на сообщение
yellyex #1904 вчера в 17:46 С помощью этого парсера, я выцепил все посты в текстовом виде. Теперь я попрошу нейронку составить подробный психологический портрет автора темы. # -*- coding: utf-8 -*- """ Парсер форума prodota.ru с выбором режима: - Режим 1 (только текст): сохраняет сообщения (автор, номер, текст) в JSON или CSV. - Режим 2 (полный парсинг): скачивает все вложения (картинки, видео, документы) и создаёт локальную HTML-копию темы, где вложения встроены или доступны по ссылкам. ДЛЯ НЕПРОГРАММИСТОВ: - Всё, что нужно настроить, находится в самом начале (раздел "НАСТРОЙКИ"). - Укажите START_URL, FOLDER_NAME, DEFAULT_OUTPUT_DIR и другие параметры. - При запуске программа попросит выбрать режим (1 или 2) – больше ничего вводить не нужно. - Если вы хотите, чтобы режим выбирался автоматически (без вопроса), установите DEFAULT_MODE = 1 или 2. """ import os import re import time import json import csv import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse, unquote from pathlib import Path # ========================== НАСТРОЙКИ (изменяйте здесь) ========================== # Режим по умолчанию (если оставить None, будет запрошен при запуске) # 1 - только текст, 2 - полный парсинг с вложениями DEFAULT_MODE = None # или 1, 2 # Ссылка на первую страницу темы (обязательно укажите!) START_URL = 'https://prodota.ru/forum/topic/224160/' # <-- ЗАМЕНИТЕ НА ВАШУ ТЕМУ # Имя папки, куда будет сохранён архив (без пробелов, латиница и цифры) FOLDER_NAME = 'prodota_archive' # <-- МОЖЕТЕ ИЗМЕНИТЬ # Папка, в которую будут сохраняться все архивы (по умолчанию – папка Download на Android) DEFAULT_OUTPUT_DIR = "/storage/emulated/0/Download" # Задержка между запросами к страницам (секунды) – чтобы не перегружать сервер DELAY = 1.5 # Таймаут для запроса (секунды) TIMEOUT = 20 # Для текстового режима: формат сохранения ('json' или 'csv') TEXT_FORMAT = 'json' # можно изменить на 'csv' # Расширения файлов для полного режима (определяют тип вложения) IMAGE_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg') VIDEO_EXTENSIONS = ('.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv') DOC_EXTENSIONS = ('.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.zip', '.rar', '.7z') ATTACH_EXTENSIONS = IMAGE_EXTENSIONS + VIDEO_EXTENSIONS + DOC_EXTENSIONS # ================================================================================= # ---------------------------------------- # Базовый класс с общими методами (загрузка страниц, парсинг постов) # ---------------------------------------- class BaseParser: def __init__(self, start_url, output_dir, delay=DELAY, timeout=TIMEOUT): self.start_url = start_url self.output_dir = Path(output_dir) self.delay = delay self.timeout = timeout self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3', }) self.posts = [] self.seen_posts = set() def get_soup(self, url): try: response = self.session.get(url, timeout=self.timeout) response.raise_for_status() if response.encoding is None: response.encoding = 'utf-8' return BeautifulSoup(response.text, 'html.parser') except Exception as e: print(f"Ошибка загрузки {url}: {e}") return None def extract_post_data(self, post_element, base_url): """Извлекает автора, номер поста и текст (без обработки вложений).""" author_elem = post_element.select_one('.cAuthorPane_author, .ipsComment_author, .author') if not author_elem: return None author = author_elem.get_text(strip=True) post_id = None if post_element.get('id'): match = re.search(r'(\d+)$', post_element.get('id')) if match: post_id = match.group(1) if not post_id: id_link = post_element.select_one('a[data-commentid]') if id_link and id_link.get('data-commentid'): post_id = id_link['data-commentid'] if not post_id: post_id = 'N/A' content_elem = post_element.select_one('.cPost_contentWrap, .ipsComment_content, .post-content') if not content_elem: return None text = content_elem.get_text(separator='\n', strip=True) return { 'author': author, 'post_number': post_id, 'content': text } def parse_page(self, url): soup = self.get_soup(url) if not soup: return None post_blocks = soup.select('li.ipsComment, div.cPost, article.ipsComment, div.post') if not post_blocks: print(" Не найдено сообщений на странице. Проверьте структуру сайта.") return None for block in post_blocks: post_data = self.extract_post_data(block, url) if post_data and post_data['post_number'] not in self.seen_posts: self.seen_posts.add(post_data['post_number']) self.posts.append(post_data) next_link = None next_elem = soup.select_one('a[rel="next"]') if next_elem and next_elem.get('href'): next_link = urljoin(url, next_elem['href']) if not next_link: pagination_next = soup.select_one('.ipsPagination_next a, .next a') if pagination_next and pagination_next.get('href'): next_link = urljoin(url, pagination_next['href']) return next_link def run(self): print(f"Начинаем парсинг: {self.start_url}") print(f"Папка для сохранения: {self.output_dir.absolute()}") current_url = self.start_url page_num = 1 while current_url: print(f"Страница {page_num}: {current_url}") next_url = self.parse_page(current_url) if next_url and next_url != current_url: current_url = next_url page_num += 1 time.sleep(self.delay) else: break print(f"\nСобрано сообщений: {len(self.posts)}") # ---------------------------------------- # Режим 1: только текст, сохраняет в JSON/CSV # ---------------------------------------- class TextParser(BaseParser): def __init__(self, start_url, output_dir, format='json'): super().__init__(start_url, output_dir) self.format = format.lower() def save(self): if self.format == 'json': output_file = self.output_dir / 'posts.json' with open(output_file, 'w', encoding='utf-8') as f: json.dump(self.posts, f, ensure_ascii=False, indent=2) print(f"Данные сохранены в {output_file}") elif self.format == 'csv': output_file = self.output_dir / 'posts.csv' with open(output_file, 'w', newline='', encoding='utf-8-sig') as f: writer = csv.DictWriter(f, fieldnames=['author', 'post_number', 'content']) writer.writeheader() writer.writerows(self.posts) print(f"Данные сохранены в {output_file}") else: print(f"Неизвестный формат {self.format}, данные не сохранены.") def run(self): super().run() self.save() # ---------------------------------------- # Режим 2: полный парсинг с вложениями и HTML-архивом # ---------------------------------------- class FullArchiver(BaseParser): def __init__(self, start_url, output_dir): super().__init__(start_url, output_dir) self.attachment_counter = 0 self.local_attachments = {} # Создаём папки для вложений self.attachments_dir = self.output_dir / 'attachments' self.images_dir = self.attachments_dir / 'images' self.videos_dir = self.attachments_dir / 'videos' self.docs_dir = self.attachments_dir / 'docs' for d in [self.attachments_dir, self.images_dir, self.videos_dir, self.docs_dir]: d.mkdir(parents=True, exist_ok=True) def download_file(self, url, subdir): parsed = urlparse(url) filename = os.path.basename(unquote(parsed.path)) if not filename or '.' not in filename: self.attachment_counter += 1 try: head = self.session.head(url, timeout=5, allow_redirects=True) content_type = head.headers.get('content-type', '') ext = self.guess_extension_by_mime(content_type) filename = f"file_{self.attachment_counter}{ext}" except: filename = f"file_{self.attachment_counter}.bin" else: filename = filename.split('?')[0] base, ext = os.path.splitext(filename) counter = 1 final_filename = filename while (subdir / final_filename).exists(): final_filename = f"{base}_{counter}{ext}" counter += 1 local_path = subdir / final_filename rel_path = local_path.relative_to(self.output_dir).as_posix() try: with self.session.get(url, stream=True, timeout=self.timeout) as r: r.raise_for_status() with open(local_path, 'wb') as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) print(f" Скачан файл: {rel_path}") return rel_path except Exception as e: print(f" Ошибка скачивания {url}: {e}") return None def guess_extension_by_mime(self, mime): mime = mime.lower() if 'image/jpeg' in mime: return '.jpg' if 'image/png' in mime: return '.png' if 'image/gif' in mime: return '.gif' if 'video/mp4' in mime: return '.mp4' if 'application/pdf' in mime: return '.pdf' return '.bin' def is_attachment_url(self, url): if not url: return False if url.startswith('#') or url.startswith('javascript:'): return False path = urlparse(url).path.lower() if any(path.endswith(ext) for ext in ATTACH_EXTENSIONS): return True if '/uploads/' in path or '/monthly_' in path or 'attachments' in path: return True return False def process_attachments_in_html(self, html_content, base_url): if not html_content: return html_content soup = BeautifulSoup(html_content, 'html.parser') for a_tag in soup.find_all('a', href=True): href = a_tag['href'] absolute_url = urljoin(base_url, href) if self.is_attachment_url(absolute_url): if absolute_url in self.local_attachments: local_path = self.local_attachments[absolute_url] else: ext = os.path.splitext(urlparse(absolute_url).path)[1].lower() if ext in IMAGE_EXTENSIONS: subdir = self.images_dir elif ext in VIDEO_EXTENSIONS: subdir = self.videos_dir else: subdir = self.docs_dir local_path = self.download_file(absolute_url, subdir) if local_path: self.local_attachments[absolute_url] = local_path else: continue a_tag['href'] = local_path if ext in IMAGE_EXTENSIONS: img_tag = soup.new_tag('img', src=local_path, alt=local_path, style="max-width:100%;") a_tag.replace_with(img_tag) elif ext in VIDEO_EXTENSIONS: video_tag = soup.new_tag('video', controls=True, style="max-width:100%;") source_tag = soup.new_tag('source', src=local_path, type='video/mp4') video_tag.append(source_tag) a_tag.replace_with(video_tag) for img_tag in soup.find_all('img', src=True): src = img_tag['src'] absolute_url = urljoin(base_url, src) if self.is_attachment_url(absolute_url): if absolute_url in self.local_attachments: local_path = self.local_attachments[absolute_url] else: local_path = self.download_file(absolute_url, self.images_dir) if local_path: self.local_attachments[absolute_url] = local_path else: continue img_tag['src'] = local_path return str(soup) def extract_post_data(self, post_element, base_url): """Переопределяем метод для обработки вложений в HTML.""" author_elem = post_element.select_one('.cAuthorPane_author, .ipsComment_author, .author') if not author_elem: return None author = author_elem.get_text(strip=True) post_id = None if post_element.get('id'): match = re.search(r'(\d+)$', post_element.get('id')) if match: post_id = match.group(1) if not post_id: id_link = post_element.select_one('a[data-commentid]') if id_link and id_link.get('data-commentid'): post_id = id_link['data-commentid'] if not post_id: post_id = 'N/A' content_elem = post_element.select_one('.cPost_contentWrap, .ipsComment_content, .post-content') if not content_elem: return None inner_html = str(content_elem) processed_html = self.process_attachments_in_html(inner_html, base_url) return { 'author': author, 'post_number': post_id, 'html': processed_html } def generate_html(self): html_template = """<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Архив темы: {title}</title> <style> body {{ font-family: Arial, sans-serif; max-width: 1000px; margin: 0 auto; padding: 20px; background: #f5f5f5; }} .post {{ background: white; border: 1px solid #ddd; border-radius: 5px; margin-bottom: 20px; padding: 15px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }} .post-header {{ border-bottom: 1px solid #eee; padding-bottom: 10px; margin-bottom: 10px; font-size: 0.9em; color: #666; }} .post-author {{ font-weight: bold; color: #333; }} .post-id {{ color: #999; margin-left: 10px; }} .post-content {{ line-height: 1.4; }} img, video {{ max-width: 100%; height: auto; margin: 10px 0; }} </style> </head> <body> <h1>Архив темы: {title}</h1> <p>Всего сообщений: {total_posts}</p> <hr> {posts_html} </body> </html> """ posts_html = [] for p in self.posts: posts_html.append(f""" <div class="post"> <div class="post-header"> <span class="post-author">{p['author']}</span> <span class="post-id">Пост #{p['post_number']}</span> </div> <div class="post-content"> {p['html']} </div> </div> """) title = "Тема с prodota.ru" final_html = html_template.format( title=title, total_posts=len(self.posts), posts_html='\n'.join(posts_html) ) return final_html def run(self): super().run() print("Генерация HTML-страницы...") html_content = self.generate_html() index_path = self.output_dir / 'index.html' with open(index_path, 'w', encoding='utf-8') as f: f.write(html_content) print(f"HTML-страница сохранена: {index_path.absolute()}") # ---------------------------------------- # Точка входа: только выбор режима # ---------------------------------------- if __name__ == '__main__': print("=== Парсер форума prodota.ru ===") # Определяем режим mode = DEFAULT_MODE if mode is None: print("Выберите режим работы:") print("1 - Только текст (сохранить в JSON/CSV)") print("2 - Полный парсинг (скачать вложения, создать HTML-архив)") mode = input("Введите 1 или 2: ").strip() while mode not in ('1', '2'): print("Ошибка: введите 1 или 2") mode = input("Введите 1 или 2: ").strip() mode = int(mode) else: print(f"Используем режим {mode} (указан в настройках)") # Проверяем, что START_URL и FOLDER_NAME заданы if not START_URL: print("ОШИБКА: переменная START_URL не задана. Отредактируйте настройки в начале кода.") exit(1) if not FOLDER_NAME: print("ОШИБКА: переменная FOLDER_NAME не задана. Отредактируйте настройки в начале кода.") exit(1) # Создаём полный путь к папке full_path = os.path.join(DEFAULT_OUTPUT_DIR, FOLDER_NAME) os.makedirs(full_path, exist_ok=True) # Запуск в зависимости от режима if mode == 1: print("\n=== Режим: только текст ===") parser = TextParser(START_URL, full_path, format=TEXT_FORMAT) parser.run() else: print("\n=== Режим: полный парсинг с вложениями ===") archiver = FullArchiver(START_URL, full_path) archiver.run() print("\nГотово! Файлы сохранены в папку:", full_path) Вот, что выдала нейронка: Привет! Пожалуйста составь подробный психологический портрет автора темы. Ник yellyex. Я скачал все посты с сайта, где он упоминается в один файл. Ответ: Конечно, вот подробный психологический портрет автора темы (ник yellyex), составленный на основе анализа предоставленных сообщений. Важно отметить, что данный портрет является аналитической реконструкцией и не может заменить клиническую диагностику. --- Психологический портрет yellyex (Елекс) 1. Центральный конфликт: Инфантилизм и Эскапизм Главная движущая сила персонажа — это глубокое желание эскапизма, побега от реальности. Он постоянно подчеркивает свое отвращение к "городу", "обществу" и "миру денег". Однако его эскапизм не является следствием зрелого выбора, а проистекает из инфантильной позиции. Он не стремится построить новую жизнь, а пытается вернуться в "детство", описывая идиллическую картину: «Ты словно маленький бегаешь босиком на лужайке перед домом в одних трусиках и радуешься солнышку». Это регрессивное желание, где все заботы о нем решает кто-то другой (сначала мама, затем — форум). 2. Личностные черты и когнитивные особенности · Амбивалентность и неспособность к действию: Он генерирует множество планов (землянка, квартира, работа в пятерочке), которые постоянно меняются и откладываются. Каждый раз, когда требуется приступить к действию (пойти копать землянку, устроиться на работу), он находит причину для отсрочки: «Я спать лег. Отдых до 2 ноября». Его действия ограничиваются приготовлениями (покупка черенка для лопаты), а не самой стройкой. Это классическая прокрастинация, подкрепленная внешним локусом контроля (он ищет причину неудач во внешних обстоятельствах, а не в себе). · Инфантильная финансовая зависимость: Для него естественно просить деньги у матери («Мамка может дать»), а после конфликта с ней — перенаправить запрос на аудиторию форума. Он искренне не видит в этом проблемы, аргументируя это тем, что зрители «покупают шмотки в кс и доте». Он не воспринимает свой "проект" как труд, за который нужно платить, а как повод для донатов. Даже когда он говорит «строю бесплатно», он тут же добавляет ссылку на донаты. · Магическое мышление и фантазийность: Его планы не имеют ничего общего с реальностью. Он собирается построить дом за 5 дней, используя сырой валежник, камни из реки и бензопилу без опыта работы с ней. Он верит, что сможет законно присвоить себе дом в заброшенной деревне, сказав, что это «дом моего прадеда». Восприятие времени и ресурсов искажено. Он искренне верит в свои грандиозные планы, что указывает на сложности с реальностью. · Низкая фрустрационная толерантность: Любое физическое или психологическое препятствие вызывает у него сильное расстройство и желание "отдохнуть". Распиленное бревно (один ствол) — это уже "рабочий день", после которого он уходит отдыхать. Отказ матери в деньгах или критика на форуме вызывают вспышки гнева и обиды. 3. Коммуникация и социальное взаимодействие · Проекция и обвинение: Он проецирует свою лень и неспособность на других. Когда ему указывают на нереалистичность планов, он обвиняет критиков в том, что они «долбоебы», которые не могут вникнуть в его ситуацию. Его защитная реакция — агрессия и обесценивание («Идите нахуй все хейтеры!»). · Поиск "идеальной" аудитории: Он хочет получать донаты и восхищение, но не хочет принимать конструктивную критику или выполнять обещанное. Он пытается выстроить нарратив "зритель платит за контент", но сам не способен этот контент произвести. Он ждет, что аудитория будет платить ему авансом за его "энтузиазм". · Искажение реальности (склонность к псевдологии): В ходе темы он несколько раз рассказывает истории, которые с высокой долей вероятности являются выдумкой или сильным преувеличением (приход ментов с изъятием бензопилы и снятием отпечатков пальцев). Эта история становится для него способом легитимно "отменить" строительство землянки, не беря на себя ответственность за неудачу. Он не просто врет, он верит в эту историю, что подтверждает его отрыв от реальности. 4. Диагностические гипотезы С большой вероятностью можно предположить наличие следующих особенностей: · Расстройство личности (возможно, шизоидного или зависимого типа): Социальная изоляция, странность мышления, эмоциональная холодность (сменяющаяся вспышками гнева), крайняя зависимость от матери и, как следствие, от мнения "значимых других" (аудитории форума). · Астенический невроз / расстройство: Он сам упоминает это. Постоянная усталость, неспособность выдерживать длительные нагрузки, потребность в длительном отдыхе после минимальных усилий — ключевые симптомы. Его знаменитое «Я спать пошел» — это квинтэссенция этого состояния. · Инфантилизм: Сочетание эмоциональной незрелости, зависимости, гедонистических установок и отсутствия ответственности за свои действия и жизнь в целом. · Высокий уровень нарциссической защиты: Его претензия на уникальность, неприятие критики, требование к аудитории воспринимать его как "художника" и спонсировать его "творчество" без доказательств. 5. Динамика и развитие персонажа Персонаж практически не развивается на протяжении всего топика. Он проживает один и тот же цикл снова и снова: 1. Грандиозный план: Объявляет о начале строительства землянки. 2. Столкновение с реальностью: Сталкивается с первой же трудностью (дождь, нет транспорта, холод). 3. Регрессия и требования: Обращается за деньгами к маме или форуму, аргументируя это тем, что без денег контент невозможен. 4. Отдых/Избегание: Вместо стройки выбирает отдых или придумывает отвлекающую активность (поездку за квартирой). 5. Рационализация и обесценивание: Объясняет неудачу внешними факторами (менты, зима, мама), обесценивает свой прошлый план ("это была временная землянка") и начинает новый цикл. Заключение Yellyex — это трагикомический образ человека, застывшего в инфантильной фазе развития. Его попытка стать "выживальщиком" — это не акт взросления, а его отрицание, попытка обрести "детство" не через преодоление трудностей, а через бегство от них. Форум для него становится не местом для отчета, а заменой родительской фигуре, которая должна обеспечить ему безопасность (деньгами и вниманием), пока он будет играть в свою "взрослую" игру. Он не просто не способен построить землянку; он не способен выйти из замкнутого круга собственных фантазий. Его уникальность заключается в том, что он стал идеальным "зеркалом" для форумного сообщества, которое в его патологическом поведении увидело развлекательный контент. E1azor и Langusto понравилось это Цитата moonfangtopich написал 29.08.2019 в 14:57: У вас недостаточно широкий кругозор, пацаны Я странствия этого еблана видел в покерных топанах, а потом в таверне - это один из самых безумных людей на форуме. Я искренне надеялся, что его зов о помощи останется незамеченным, но нет, нашелся доброволец и вот уже три страницы мы пожинаем плоды Поделиться сообщением Ссылка на сообщение
Son of Anarchy #1905 вчера в 17:52 бля вы мне за фотки еще че то говорите тут ваще шиза не реальная yellyex и Qreeq понравилось это Цитата Поделиться сообщением Ссылка на сообщение
Qreeq #1906 вчера в 17:53 Да тут вообще пиздец yellyex понравилось это Цитата Поделиться сообщением Ссылка на сообщение
yellyex #1907 вчера в 17:57 Я пока читал несколько раз проплакался от смеха. Надо топики русверса также прогнать. Где он там обитает? 🤣🤣🤣 Запрос: Нужен полный диагноз. Может он шизик и опасен для общества. Ответ: Поскольку я — искусственный интеллект, а не психиатр, я не могу поставить клинический диагноз. Это может сделать только врач после личной беседы и обследования. Однако на основе анализа предоставленных данных я могу описать наблюдаемые психопатологические феномены и дать экспертную оценку возможных рисков. --- Анализ наблюдаемых признаков 1. Отсутствие признаков психотического распада Вывод: Нет оснований говорить о шизофрении или бредовом расстройстве в классическом понимании. У yellyex отсутствуют ключевые признаки психоза: · Нет галлюцинаций. Он не утверждает, что слышит голоса или видит то, чего нет. · Нет систематизированного бреда. Его идеи (построить землянку, подключиться к столбу) — это фантазии, основанные на незнании реальности и инфантильном мышлении, а не на бредовых убеждениях, которым он слепо следует. Он способен менять планы, реагировать на критику (пусть и агрессивно), что нехарактерно для больного с бредом. · Сохранена ориентировка. Он понимает, где находится, кто он, какой сейчас год. · Эпизоды «искажения реальности» (история с ментами) больше похожи на псевдологию (патологическую ложь) с целью избежать ответственности за провал, а не на бред. 2. Структура личности: Расстройство личности с пограничными чертами и зависимостью Наиболее вероятная диагностическая гипотеза — это смешанное расстройство личности с доминированием зависимых, шизоидных и нарциссических черт. · Зависимое расстройство личности (F60.7): · Неспособность принимать решения без чрезмерных советов и поддержки (постоянное согласование планов с форумом). · Пассивная позиция в финансовых вопросах (ожидание денег от мамы и донатов). · Поиск «опекающей» фигуры (сначала мать, потом форум). · Шизоидное расстройство личности (F60.1): · Предпочтение уединенной деятельности. · Отсутствие близких дружеских и романтических связей (сам признается, что секса с женщиной не было и не хочет). · Эмоциональная холодность и отстраненность, сменяющаяся вспышками гнева. · Ограниченная способность выражать чувства. · Нарциссические черты (не полное расстройство): · Грандиозность планов при отсутствии достижений. · Ожидание особого отношения (дотаты, внимание форума без предоставления реального контента). · Непереносимость критики с гневными реакциями обесценивания («идите нахуй»). 3. Невротический уровень функционирования · Астенический невроз (синдром): Постоянная усталость, неспособность выдерживать физическую и психологическую нагрузку, потребность в длительном отдыхе после минимальных усилий — центральная проблема, которую он сам осознает. · Инфантилизм: Ядро его личности. Сочетание интеллектуальной сохранности (способен строить сложные планы, писать код) с полной эмоциональной и социальной незрелостью. Он играет во «взрослого выживальщика», как ребенок играет в войнушку, но искренне верит в свою игру. --- Оценка опасности для общества Низкая. Он не опасен для окружающих. 1. Отсутствие агрессивных импульсов. Его гнев — вербальный, защитный. Он не угрожает насилием, не описывает фантазий насилия над людьми (история с ментами — это история о нем как о жертве, а не агрессоре). 2. Нет параноидной направленности. Он не подозревает окружающих в заговорах против него, не ищет врагов. 3. Его действия направлены на самоизоляцию, а не на вторжение в чужую жизнь. Максимум, что ему грозит — это административное правонарушение (незаконное подключение к электросетям, незаконная вырубка леса), но не уголовные преступления против личности. Высокий риск аутодеструктивного поведения (опасен для себя). · Высокая вероятность травматизма. Работа с бензопилой без опыта, строительство без навыков, нахождение в лесу в одиночестве без связи и запаса еды. · Риск переохлаждения, ожогов, отравления угарным газом. Его планы печей из камней и глины без дымохода — это прямой путь к летальному исходу. · Риск суицидального поведения на фоне краха идеалов. Если его очередная попытка закончится полным провалом, он может впасть в тяжелую депрессию. Его навязчивая идея «уйти в лес» может трансформироваться в пассивное желание «не вернуться». --- Заключение Yellyex не является «шизиком» в бытовом смысле. У него нет психоза, он не опасен для окружающих. Его состояние укладывается в рамки сложного расстройства личности (вероятно, смешанного, с преобладанием зависимых и шизоидных черт) на невротическом уровне, осложненного инфантилизмом и астеническим синдромом. Главная угроза, которую он представляет, — это угроза самому себе. Его эскапады в лес — это не преступный умысел, а способ саморазрушения через некомпетентность. Рекомендации: · Не нуждается в изоляции или принудительном лечении. · Остро нуждается в длительной психотерапии (когнитивно-поведенческая или психоаналитическая терапия расстройств личности) и, возможно, в медикаментозной поддержке (антидепрессанты) для коррекции астенического и тревожного компонентов. · Близким (матери) рекомендуется прекратить финансовое поощрение его инфантильных проектов и мягко, но настойчиво направлять его к психиатру и психотерапевту для плановой работы, а не для «спасения» после очередной неудачной вылазки. NaxrenApm понравилось это Цитата moonfangtopich написал 29.08.2019 в 14:57: У вас недостаточно широкий кругозор, пацаны Я странствия этого еблана видел в покерных топанах, а потом в таверне - это один из самых безумных людей на форуме. Я искренне надеялся, что его зов о помощи останется незамеченным, но нет, нашелся доброволец и вот уже три страницы мы пожинаем плоды Поделиться сообщением Ссылка на сообщение
Qreeq #1908 вчера в 18:10 yellyex написал 13 минут назад: секса с женщиной не было и не хочет Единственный признак, почему елекса можно считать здоровым человеком Цитата Поделиться сообщением Ссылка на сообщение
yellyex #1909 вчера в 18:19 Сейчас я скормлю нейронке тему Отдыха. Пусть ознакомится и дополнит психологический портрет. https://prodota.ru/forum/topic/212849/?ysclid=mngd89mxix985021776 Цитата moonfangtopich написал 29.08.2019 в 14:57: У вас недостаточно широкий кругозор, пацаны Я странствия этого еблана видел в покерных топанах, а потом в таверне - это один из самых безумных людей на форуме. Я искренне надеялся, что его зов о помощи останется незамеченным, но нет, нашелся доброволец и вот уже три страницы мы пожинаем плоды Поделиться сообщением Ссылка на сообщение
insigniA #1910 вчера в 18:38 Мла, я бы не отказался посмотреть, как это чудо полезло бы на столб "чето там подключать" Цитата 2.) алоха - гремлин ебаный, с него только ржать можно. Если бы не был олигофреном, то мог капитанить, проталкивать свои идеи и результат был бы лучше. Поделиться сообщением Ссылка на сообщение
yellyex #1911 вчера в 18:52 insigniA написал 13 минут назад: Мла, я бы не отказался посмотреть, как это чудо полезло бы на столб "чето там подключать" 15к и можно будет посмотреть. Цитата moonfangtopich написал 29.08.2019 в 14:57: У вас недостаточно широкий кругозор, пацаны Я странствия этого еблана видел в покерных топанах, а потом в таверне - это один из самых безумных людей на форуме. Я искренне надеялся, что его зов о помощи останется незамеченным, но нет, нашелся доброволец и вот уже три страницы мы пожинаем плоды Поделиться сообщением Ссылка на сообщение
Qreeq #1912 вчера в 18:54 (изменено) del. сори Изменено вчера в 19:00 пользователем Qreeq Цитата Поделиться сообщением Ссылка на сообщение
Gomosek #1913 вчера в 18:55 Закинь этой своей проге все три полит топика, целиком. Пусть найдет в них самых отбитых шизофреника. Хотя думаю может перегореть и загючить bitrix, Methamphetamine, Herokills и 1 другому понравилось это Цитата Поделиться сообщением Ссылка на сообщение
Ratio #1914 вчера в 18:58 (изменено) yellyex написал 1 час назад: С помощью этого парсера, я выцепил все посты в текстовом виде. Теперь я попрошу нейронку составить подробный психологический портрет автора темы. # -*- coding: utf-8 -*- """ Парсер форума prodota.ru с выбором режима: - Режим 1 (только текст): сохраняет сообщения (автор, номер, текст) в JSON или CSV. - Режим 2 (полный парсинг): скачивает все вложения (картинки, видео, документы) и создаёт локальную HTML-копию темы, где вложения встроены или доступны по ссылкам. ДЛЯ НЕПРОГРАММИСТОВ: - Всё, что нужно настроить, находится в самом начале (раздел "НАСТРОЙКИ"). - Укажите START_URL, FOLDER_NAME, DEFAULT_OUTPUT_DIR и другие параметры. - При запуске программа попросит выбрать режим (1 или 2) – больше ничего вводить не нужно. - Если вы хотите, чтобы режим выбирался автоматически (без вопроса), установите DEFAULT_MODE = 1 или 2. """ import os import re import time import json import csv import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse, unquote from pathlib import Path # ========================== НАСТРОЙКИ (изменяйте здесь) ========================== # Режим по умолчанию (если оставить None, будет запрошен при запуске) # 1 - только текст, 2 - полный парсинг с вложениями DEFAULT_MODE = None # или 1, 2 # Ссылка на первую страницу темы (обязательно укажите!) START_URL = 'https://prodota.ru/forum/topic/224160/' # <-- ЗАМЕНИТЕ НА ВАШУ ТЕМУ # Имя папки, куда будет сохранён архив (без пробелов, латиница и цифры) FOLDER_NAME = 'prodota_archive' # <-- МОЖЕТЕ ИЗМЕНИТЬ # Папка, в которую будут сохраняться все архивы (по умолчанию – папка Download на Android) DEFAULT_OUTPUT_DIR = "/storage/emulated/0/Download" # Задержка между запросами к страницам (секунды) – чтобы не перегружать сервер DELAY = 1.5 # Таймаут для запроса (секунды) TIMEOUT = 20 # Для текстового режима: формат сохранения ('json' или 'csv') TEXT_FORMAT = 'json' # можно изменить на 'csv' # Расширения файлов для полного режима (определяют тип вложения) IMAGE_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg') VIDEO_EXTENSIONS = ('.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv') DOC_EXTENSIONS = ('.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.zip', '.rar', '.7z') ATTACH_EXTENSIONS = IMAGE_EXTENSIONS + VIDEO_EXTENSIONS + DOC_EXTENSIONS # ================================================================================= # ---------------------------------------- # Базовый класс с общими методами (загрузка страниц, парсинг постов) # ---------------------------------------- class BaseParser: def __init__(self, start_url, output_dir, delay=DELAY, timeout=TIMEOUT): self.start_url = start_url self.output_dir = Path(output_dir) self.delay = delay self.timeout = timeout self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3', }) self.posts = [] self.seen_posts = set() def get_soup(self, url): try: response = self.session.get(url, timeout=self.timeout) response.raise_for_status() if response.encoding is None: response.encoding = 'utf-8' return BeautifulSoup(response.text, 'html.parser') except Exception as e: print(f"Ошибка загрузки {url}: {e}") return None def extract_post_data(self, post_element, base_url): """Извлекает автора, номер поста и текст (без обработки вложений).""" author_elem = post_element.select_one('.cAuthorPane_author, .ipsComment_author, .author') if not author_elem: return None author = author_elem.get_text(strip=True) post_id = None if post_element.get('id'): match = re.search(r'(\d+)$', post_element.get('id')) if match: post_id = match.group(1) if not post_id: id_link = post_element.select_one('a[data-commentid]') if id_link and id_link.get('data-commentid'): post_id = id_link['data-commentid'] if not post_id: post_id = 'N/A' content_elem = post_element.select_one('.cPost_contentWrap, .ipsComment_content, .post-content') if not content_elem: return None text = content_elem.get_text(separator='\n', strip=True) return { 'author': author, 'post_number': post_id, 'content': text } def parse_page(self, url): soup = self.get_soup(url) if not soup: return None post_blocks = soup.select('li.ipsComment, div.cPost, article.ipsComment, div.post') if not post_blocks: print(" Не найдено сообщений на странице. Проверьте структуру сайта.") return None for block in post_blocks: post_data = self.extract_post_data(block, url) if post_data and post_data['post_number'] not in self.seen_posts: self.seen_posts.add(post_data['post_number']) self.posts.append(post_data) next_link = None next_elem = soup.select_one('a[rel="next"]') if next_elem and next_elem.get('href'): next_link = urljoin(url, next_elem['href']) if not next_link: pagination_next = soup.select_one('.ipsPagination_next a, .next a') if pagination_next and pagination_next.get('href'): next_link = urljoin(url, pagination_next['href']) return next_link def run(self): print(f"Начинаем парсинг: {self.start_url}") print(f"Папка для сохранения: {self.output_dir.absolute()}") current_url = self.start_url page_num = 1 while current_url: print(f"Страница {page_num}: {current_url}") next_url = self.parse_page(current_url) if next_url and next_url != current_url: current_url = next_url page_num += 1 time.sleep(self.delay) else: break print(f"\nСобрано сообщений: {len(self.posts)}") # ---------------------------------------- # Режим 1: только текст, сохраняет в JSON/CSV # ---------------------------------------- class TextParser(BaseParser): def __init__(self, start_url, output_dir, format='json'): super().__init__(start_url, output_dir) self.format = format.lower() def save(self): if self.format == 'json': output_file = self.output_dir / 'posts.json' with open(output_file, 'w', encoding='utf-8') as f: json.dump(self.posts, f, ensure_ascii=False, indent=2) print(f"Данные сохранены в {output_file}") elif self.format == 'csv': output_file = self.output_dir / 'posts.csv' with open(output_file, 'w', newline='', encoding='utf-8-sig') as f: writer = csv.DictWriter(f, fieldnames=['author', 'post_number', 'content']) writer.writeheader() writer.writerows(self.posts) print(f"Данные сохранены в {output_file}") else: print(f"Неизвестный формат {self.format}, данные не сохранены.") def run(self): super().run() self.save() # ---------------------------------------- # Режим 2: полный парсинг с вложениями и HTML-архивом # ---------------------------------------- class FullArchiver(BaseParser): def __init__(self, start_url, output_dir): super().__init__(start_url, output_dir) self.attachment_counter = 0 self.local_attachments = {} # Создаём папки для вложений self.attachments_dir = self.output_dir / 'attachments' self.images_dir = self.attachments_dir / 'images' self.videos_dir = self.attachments_dir / 'videos' self.docs_dir = self.attachments_dir / 'docs' for d in [self.attachments_dir, self.images_dir, self.videos_dir, self.docs_dir]: d.mkdir(parents=True, exist_ok=True) def download_file(self, url, subdir): parsed = urlparse(url) filename = os.path.basename(unquote(parsed.path)) if not filename or '.' not in filename: self.attachment_counter += 1 try: head = self.session.head(url, timeout=5, allow_redirects=True) content_type = head.headers.get('content-type', '') ext = self.guess_extension_by_mime(content_type) filename = f"file_{self.attachment_counter}{ext}" except: filename = f"file_{self.attachment_counter}.bin" else: filename = filename.split('?')[0] base, ext = os.path.splitext(filename) counter = 1 final_filename = filename while (subdir / final_filename).exists(): final_filename = f"{base}_{counter}{ext}" counter += 1 local_path = subdir / final_filename rel_path = local_path.relative_to(self.output_dir).as_posix() try: with self.session.get(url, stream=True, timeout=self.timeout) as r: r.raise_for_status() with open(local_path, 'wb') as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) print(f" Скачан файл: {rel_path}") return rel_path except Exception as e: print(f" Ошибка скачивания {url}: {e}") return None def guess_extension_by_mime(self, mime): mime = mime.lower() if 'image/jpeg' in mime: return '.jpg' if 'image/png' in mime: return '.png' if 'image/gif' in mime: return '.gif' if 'video/mp4' in mime: return '.mp4' if 'application/pdf' in mime: return '.pdf' return '.bin' def is_attachment_url(self, url): if not url: return False if url.startswith('#') or url.startswith('javascript:'): return False path = urlparse(url).path.lower() if any(path.endswith(ext) for ext in ATTACH_EXTENSIONS): return True if '/uploads/' in path or '/monthly_' in path or 'attachments' in path: return True return False def process_attachments_in_html(self, html_content, base_url): if not html_content: return html_content soup = BeautifulSoup(html_content, 'html.parser') for a_tag in soup.find_all('a', href=True): href = a_tag['href'] absolute_url = urljoin(base_url, href) if self.is_attachment_url(absolute_url): if absolute_url in self.local_attachments: local_path = self.local_attachments[absolute_url] else: ext = os.path.splitext(urlparse(absolute_url).path)[1].lower() if ext in IMAGE_EXTENSIONS: subdir = self.images_dir elif ext in VIDEO_EXTENSIONS: subdir = self.videos_dir else: subdir = self.docs_dir local_path = self.download_file(absolute_url, subdir) if local_path: self.local_attachments[absolute_url] = local_path else: continue a_tag['href'] = local_path if ext in IMAGE_EXTENSIONS: img_tag = soup.new_tag('img', src=local_path, alt=local_path, style="max-width:100%;") a_tag.replace_with(img_tag) elif ext in VIDEO_EXTENSIONS: video_tag = soup.new_tag('video', controls=True, style="max-width:100%;") source_tag = soup.new_tag('source', src=local_path, type='video/mp4') video_tag.append(source_tag) a_tag.replace_with(video_tag) for img_tag in soup.find_all('img', src=True): src = img_tag['src'] absolute_url = urljoin(base_url, src) if self.is_attachment_url(absolute_url): if absolute_url in self.local_attachments: local_path = self.local_attachments[absolute_url] else: local_path = self.download_file(absolute_url, self.images_dir) if local_path: self.local_attachments[absolute_url] = local_path else: continue img_tag['src'] = local_path return str(soup) def extract_post_data(self, post_element, base_url): """Переопределяем метод для обработки вложений в HTML.""" author_elem = post_element.select_one('.cAuthorPane_author, .ipsComment_author, .author') if not author_elem: return None author = author_elem.get_text(strip=True) post_id = None if post_element.get('id'): match = re.search(r'(\d+)$', post_element.get('id')) if match: post_id = match.group(1) if not post_id: id_link = post_element.select_one('a[data-commentid]') if id_link and id_link.get('data-commentid'): post_id = id_link['data-commentid'] if not post_id: post_id = 'N/A' content_elem = post_element.select_one('.cPost_contentWrap, .ipsComment_content, .post-content') if not content_elem: return None inner_html = str(content_elem) processed_html = self.process_attachments_in_html(inner_html, base_url) return { 'author': author, 'post_number': post_id, 'html': processed_html } def generate_html(self): html_template = """<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Архив темы: {title}</title> <style> body {{ font-family: Arial, sans-serif; max-width: 1000px; margin: 0 auto; padding: 20px; background: #f5f5f5; }} .post {{ background: white; border: 1px solid #ddd; border-radius: 5px; margin-bottom: 20px; padding: 15px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }} .post-header {{ border-bottom: 1px solid #eee; padding-bottom: 10px; margin-bottom: 10px; font-size: 0.9em; color: #666; }} .post-author {{ font-weight: bold; color: #333; }} .post-id {{ color: #999; margin-left: 10px; }} .post-content {{ line-height: 1.4; }} img, video {{ max-width: 100%; height: auto; margin: 10px 0; }} </style> </head> <body> <h1>Архив темы: {title}</h1> <p>Всего сообщений: {total_posts}</p> <hr> {posts_html} </body> </html> """ posts_html = [] for p in self.posts: posts_html.append(f""" <div class="post"> <div class="post-header"> <span class="post-author">{p['author']}</span> <span class="post-id">Пост #{p['post_number']}</span> </div> <div class="post-content"> {p['html']} </div> </div> """) title = "Тема с prodota.ru" final_html = html_template.format( title=title, total_posts=len(self.posts), posts_html='\n'.join(posts_html) ) return final_html def run(self): super().run() print("Генерация HTML-страницы...") html_content = self.generate_html() index_path = self.output_dir / 'index.html' with open(index_path, 'w', encoding='utf-8') as f: f.write(html_content) print(f"HTML-страница сохранена: {index_path.absolute()}") # ---------------------------------------- # Точка входа: только выбор режима # ---------------------------------------- if __name__ == '__main__': print("=== Парсер форума prodota.ru ===") # Определяем режим mode = DEFAULT_MODE if mode is None: print("Выберите режим работы:") print("1 - Только текст (сохранить в JSON/CSV)") print("2 - Полный парсинг (скачать вложения, создать HTML-архив)") mode = input("Введите 1 или 2: ").strip() while mode not in ('1', '2'): print("Ошибка: введите 1 или 2") mode = input("Введите 1 или 2: ").strip() mode = int(mode) else: print(f"Используем режим {mode} (указан в настройках)") # Проверяем, что START_URL и FOLDER_NAME заданы if not START_URL: print("ОШИБКА: переменная START_URL не задана. Отредактируйте настройки в начале кода.") exit(1) if not FOLDER_NAME: print("ОШИБКА: переменная FOLDER_NAME не задана. Отредактируйте настройки в начале кода.") exit(1) # Создаём полный путь к папке full_path = os.path.join(DEFAULT_OUTPUT_DIR, FOLDER_NAME) os.makedirs(full_path, exist_ok=True) # Запуск в зависимости от режима if mode == 1: print("\n=== Режим: только текст ===") parser = TextParser(START_URL, full_path, format=TEXT_FORMAT) parser.run() else: print("\n=== Режим: полный парсинг с вложениями ===") archiver = FullArchiver(START_URL, full_path) archiver.run() print("\nГотово! Файлы сохранены в папку:", full_path) Вот, что выдала нейронка: Привет! Пожалуйста составь подробный психологический портрет автора темы. Ник yellyex. Я скачал все посты с сайта, где он упоминается в один файл. Ответ: Конечно, вот подробный психологический портрет автора темы (ник yellyex), составленный на основе анализа предоставленных сообщений. Важно отметить, что данный портрет является аналитической реконструкцией и не может заменить клиническую диагностику. --- Психологический портрет yellyex (Елекс) 1. Центральный конфликт: Инфантилизм и Эскапизм Главная движущая сила персонажа — это глубокое желание эскапизма, побега от реальности. Он постоянно подчеркивает свое отвращение к "городу", "обществу" и "миру денег". Однако его эскапизм не является следствием зрелого выбора, а проистекает из инфантильной позиции. Он не стремится построить новую жизнь, а пытается вернуться в "детство", описывая идиллическую картину: «Ты словно маленький бегаешь босиком на лужайке перед домом в одних трусиках и радуешься солнышку». Это регрессивное желание, где все заботы о нем решает кто-то другой (сначала мама, затем — форум). 2. Личностные черты и когнитивные особенности · Амбивалентность и неспособность к действию: Он генерирует множество планов (землянка, квартира, работа в пятерочке), которые постоянно меняются и откладываются. Каждый раз, когда требуется приступить к действию (пойти копать землянку, устроиться на работу), он находит причину для отсрочки: «Я спать лег. Отдых до 2 ноября». Его действия ограничиваются приготовлениями (покупка черенка для лопаты), а не самой стройкой. Это классическая прокрастинация, подкрепленная внешним локусом контроля (он ищет причину неудач во внешних обстоятельствах, а не в себе). · Инфантильная финансовая зависимость: Для него естественно просить деньги у матери («Мамка может дать»), а после конфликта с ней — перенаправить запрос на аудиторию форума. Он искренне не видит в этом проблемы, аргументируя это тем, что зрители «покупают шмотки в кс и доте». Он не воспринимает свой "проект" как труд, за который нужно платить, а как повод для донатов. Даже когда он говорит «строю бесплатно», он тут же добавляет ссылку на донаты. · Магическое мышление и фантазийность: Его планы не имеют ничего общего с реальностью. Он собирается построить дом за 5 дней, используя сырой валежник, камни из реки и бензопилу без опыта работы с ней. Он верит, что сможет законно присвоить себе дом в заброшенной деревне, сказав, что это «дом моего прадеда». Восприятие времени и ресурсов искажено. Он искренне верит в свои грандиозные планы, что указывает на сложности с реальностью. · Низкая фрустрационная толерантность: Любое физическое или психологическое препятствие вызывает у него сильное расстройство и желание "отдохнуть". Распиленное бревно (один ствол) — это уже "рабочий день", после которого он уходит отдыхать. Отказ матери в деньгах или критика на форуме вызывают вспышки гнева и обиды. 3. Коммуникация и социальное взаимодействие · Проекция и обвинение: Он проецирует свою лень и неспособность на других. Когда ему указывают на нереалистичность планов, он обвиняет критиков в том, что они «долбоебы», которые не могут вникнуть в его ситуацию. Его защитная реакция — агрессия и обесценивание («Идите нахуй все хейтеры!»). · Поиск "идеальной" аудитории: Он хочет получать донаты и восхищение, но не хочет принимать конструктивную критику или выполнять обещанное. Он пытается выстроить нарратив "зритель платит за контент", но сам не способен этот контент произвести. Он ждет, что аудитория будет платить ему авансом за его "энтузиазм". · Искажение реальности (склонность к псевдологии): В ходе темы он несколько раз рассказывает истории, которые с высокой долей вероятности являются выдумкой или сильным преувеличением (приход ментов с изъятием бензопилы и снятием отпечатков пальцев). Эта история становится для него способом легитимно "отменить" строительство землянки, не беря на себя ответственность за неудачу. Он не просто врет, он верит в эту историю, что подтверждает его отрыв от реальности. 4. Диагностические гипотезы С большой вероятностью можно предположить наличие следующих особенностей: · Расстройство личности (возможно, шизоидного или зависимого типа): Социальная изоляция, странность мышления, эмоциональная холодность (сменяющаяся вспышками гнева), крайняя зависимость от матери и, как следствие, от мнения "значимых других" (аудитории форума). · Астенический невроз / расстройство: Он сам упоминает это. Постоянная усталость, неспособность выдерживать длительные нагрузки, потребность в длительном отдыхе после минимальных усилий — ключевые симптомы. Его знаменитое «Я спать пошел» — это квинтэссенция этого состояния. · Инфантилизм: Сочетание эмоциональной незрелости, зависимости, гедонистических установок и отсутствия ответственности за свои действия и жизнь в целом. · Высокий уровень нарциссической защиты: Его претензия на уникальность, неприятие критики, требование к аудитории воспринимать его как "художника" и спонсировать его "творчество" без доказательств. 5. Динамика и развитие персонажа Персонаж практически не развивается на протяжении всего топика. Он проживает один и тот же цикл снова и снова: 1. Грандиозный план: Объявляет о начале строительства землянки. 2. Столкновение с реальностью: Сталкивается с первой же трудностью (дождь, нет транспорта, холод). 3. Регрессия и требования: Обращается за деньгами к маме или форуму, аргументируя это тем, что без денег контент невозможен. 4. Отдых/Избегание: Вместо стройки выбирает отдых или придумывает отвлекающую активность (поездку за квартирой). 5. Рационализация и обесценивание: Объясняет неудачу внешними факторами (менты, зима, мама), обесценивает свой прошлый план ("это была временная землянка") и начинает новый цикл. Заключение Yellyex — это трагикомический образ человека, застывшего в инфантильной фазе развития. Его попытка стать "выживальщиком" — это не акт взросления, а его отрицание, попытка обрести "детство" не через преодоление трудностей, а через бегство от них. Форум для него становится не местом для отчета, а заменой родительской фигуре, которая должна обеспечить ему безопасность (деньгами и вниманием), пока он будет играть в свою "взрослую" игру. Он не просто не способен построить землянку; он не способен выйти из замкнутого круга собственных фантазий. Его уникальность заключается в том, что он стал идеальным "зеркалом" для форумного сообщества, которое в его патологическом поведении увидело развлекательный контент. Чел, я тебе выше всё это доступно описал. Я лучше нейронки получается Изменено вчера в 19:00 пользователем Ratio Цитата Поделиться сообщением Ссылка на сообщение
yellyex #1915 вчера в 19:01 Gomosek написал 6 минут назад: Закинь этой своей проге все три полит топика, целиком. Пусть найдет в них самых отбитых шизофреника. Хотя думаю может перегореть и загючить Сейчас доделаю парсер, чтобы он мог разбить файл на части и сам можешь попробовать. Цитата moonfangtopich написал 29.08.2019 в 14:57: У вас недостаточно широкий кругозор, пацаны Я странствия этого еблана видел в покерных топанах, а потом в таверне - это один из самых безумных людей на форуме. Я искренне надеялся, что его зов о помощи останется незамеченным, но нет, нашелся доброволец и вот уже три страницы мы пожинаем плоды Поделиться сообщением Ссылка на сообщение
Ratio #1916 вчера в 19:02 Qreeq написал 7 минут назад: Еще раз цифру 15к назовешь, я лично приеду тебе ебало бить долбоебу Его там лунтик хуем наказывать собирался. Чем закончилось ? Цитата Поделиться сообщением Ссылка на сообщение
yellyex #1917 вчера в 19:03 Обновлённый код: Скрытый текст # -*- coding: utf-8 -*- """ Парсер форума prodota.ru с выбором режима: - Режим 1 (только текст): сохраняет сообщения (автор, номер, текст) в JSON или CSV. Поддерживает разбивку на части заданного размера (в МБ). - Режим 2 (полный парсинг): скачивает все вложения (картинки, видео, документы) и создаёт локальную HTML-копию темы. ДЛЯ НЕПРОГРАММИСТОВ: - Все настройки (URL, имя папки, путь сохранения и т.д.) находятся в разделе "НАСТРОЙКИ" в начале кода. - При запуске программа спросит режим (1 или 2). Если выбран режим 1, дополнительно спросит, нужно ли разбить результат на части и какой максимальный размер части в мегабайтах. - Если вы хотите, чтобы режим выбирался автоматически, установите DEFAULT_MODE = 1 или 2. """ import os import re import time import json import csv import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse, unquote from pathlib import Path # ========================== НАСТРОЙКИ (изменяйте здесь) ========================== # Режим по умолчанию (если оставить None, будет запрошен при запуске) # 1 - только текст, 2 - полный парсинг с вложениями DEFAULT_MODE = None # или 1, 2 # Ссылка на первую страницу темы (обязательно укажите!) START_URL = 'https://prodota.ru/forum/topic/224160/' # <-- ЗАМЕНИТЕ НА ВАШУ ТЕМУ # Имя папки, куда будет сохранён архив (без пробелов, латиница и цифры) FOLDER_NAME = 'prodota_archive' # <-- МОЖЕТЕ ИЗМЕНИТЬ # Папка, в которую будут сохраняться все архивы (по умолчанию – папка Download на Android) DEFAULT_OUTPUT_DIR = "/storage/emulated/0/Download" # Задержка между запросами к страницам (секунды) – чтобы не перегружать сервер DELAY = 1.5 # Таймаут для запроса (секунды) TIMEOUT = 20 # Для текстового режима: формат сохранения ('json' или 'csv') TEXT_FORMAT = 'json' # можно изменить на 'csv' # Расширения файлов для полного режима (определяют тип вложения) IMAGE_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg') VIDEO_EXTENSIONS = ('.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv') DOC_EXTENSIONS = ('.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.zip', '.rar', '.7z') ATTACH_EXTENSIONS = IMAGE_EXTENSIONS + VIDEO_EXTENSIONS + DOC_EXTENSIONS # ================================================================================= # ---------------------------------------- # Базовый класс с общими методами (загрузка страниц, парсинг постов) # ---------------------------------------- class BaseParser: def __init__(self, start_url, output_dir, delay=DELAY, timeout=TIMEOUT): self.start_url = start_url self.output_dir = Path(output_dir) self.delay = delay self.timeout = timeout self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3', }) self.posts = [] self.seen_posts = set() def get_soup(self, url): try: response = self.session.get(url, timeout=self.timeout) response.raise_for_status() if response.encoding is None: response.encoding = 'utf-8' return BeautifulSoup(response.text, 'html.parser') except Exception as e: print(f"Ошибка загрузки {url}: {e}") return None def extract_post_data(self, post_element, base_url): """Извлекает автора, номер поста и текст (без обработки вложений).""" author_elem = post_element.select_one('.cAuthorPane_author, .ipsComment_author, .author') if not author_elem: return None author = author_elem.get_text(strip=True) post_id = None if post_element.get('id'): match = re.search(r'(\d+)$', post_element.get('id')) if match: post_id = match.group(1) if not post_id: id_link = post_element.select_one('a[data-commentid]') if id_link and id_link.get('data-commentid'): post_id = id_link['data-commentid'] if not post_id: post_id = 'N/A' content_elem = post_element.select_one('.cPost_contentWrap, .ipsComment_content, .post-content') if not content_elem: return None text = content_elem.get_text(separator='\n', strip=True) return { 'author': author, 'post_number': post_id, 'content': text } def parse_page(self, url): soup = self.get_soup(url) if not soup: return None post_blocks = soup.select('li.ipsComment, div.cPost, article.ipsComment, div.post') if not post_blocks: print(" Не найдено сообщений на странице. Проверьте структуру сайта.") return None for block in post_blocks: post_data = self.extract_post_data(block, url) if post_data and post_data['post_number'] not in self.seen_posts: self.seen_posts.add(post_data['post_number']) self.posts.append(post_data) next_link = None next_elem = soup.select_one('a[rel="next"]') if next_elem and next_elem.get('href'): next_link = urljoin(url, next_elem['href']) if not next_link: pagination_next = soup.select_one('.ipsPagination_next a, .next a') if pagination_next and pagination_next.get('href'): next_link = urljoin(url, pagination_next['href']) return next_link def run(self): print(f"Начинаем парсинг: {self.start_url}") print(f"Папка для сохранения: {self.output_dir.absolute()}") current_url = self.start_url page_num = 1 while current_url: print(f"Страница {page_num}: {current_url}") next_url = self.parse_page(current_url) if next_url and next_url != current_url: current_url = next_url page_num += 1 time.sleep(self.delay) else: break print(f"\nСобрано сообщений: {len(self.posts)}") # ---------------------------------------- # Режим 1: только текст, сохраняет в JSON/CSV с возможностью разбивки # ---------------------------------------- class TextParser(BaseParser): def __init__(self, start_url, output_dir, format='json', split_size_mb=0): super().__init__(start_url, output_dir) self.format = format.lower() self.split_size_mb = split_size_mb # 0 = не разбивать def _split_and_save_json(self, data): """Разбивает список записей на несколько JSON-файлов заданного размера.""" # Сначала сериализуем весь список в строку, чтобы узнать общий размер full_json = json.dumps(data, ensure_ascii=False, indent=2) full_size = len(full_json.encode('utf-8')) max_size = self.split_size_mb * 1024 * 1024 if full_size <= max_size: # Файл помещается в один output_file = self.output_dir / 'posts.json' with open(output_file, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) print(f"Данные сохранены в {output_file}") return # Нужно разбить – определяем количество записей в каждой части # Приблизительно: берём средний размер одной записи avg_record_size = full_size / len(data) records_per_part = int(max_size / avg_record_size) + 1 part = 1 for i in range(0, len(data), records_per_part): part_data = data[i:i+records_per_part] output_file = self.output_dir / f'posts_part{part}.json' with open(output_file, 'w', encoding='utf-8') as f: json.dump(part_data, f, ensure_ascii=False, indent=2) print(f"Часть {part} сохранена: {output_file}") part += 1 def _split_and_save_csv(self, data): """Разбивает CSV на несколько файлов, сохраняя заголовки в каждом.""" max_size = self.split_size_mb * 1024 * 1024 # Сначала пишем всё во временный файл, чтобы определить разбиение temp_file = self.output_dir / '_temp.csv' with open(temp_file, 'w', newline='', encoding='utf-8-sig') as f: writer = csv.DictWriter(f, fieldnames=['author', 'post_number', 'content']) writer.writeheader() writer.writerows(data) # Читаем строки, считаем размер lines = [] with open(temp_file, 'r', encoding='utf-8-sig') as f: lines = f.readlines() # Заголовок (первая строка) header = lines[0] # Убираем заголовок из списка data_lines = lines[1:] # Определяем разбиение current_part = [] current_size = len(header.encode('utf-8')) part_num = 1 for line in data_lines: line_size = len(line.encode('utf-8')) if current_size + line_size > max_size and current_part: # Сохраняем текущую часть part_file = self.output_dir / f'posts_part{part_num}.csv' with open(part_file, 'w', newline='', encoding='utf-8-sig') as f: f.write(header) f.writelines(current_part) print(f"Часть {part_num} сохранена: {part_file}") # Начинаем новую часть part_num += 1 current_part = [line] current_size = len(header.encode('utf-8')) + line_size else: current_part.append(line) current_size += line_size # Последняя часть if current_part: part_file = self.output_dir / f'posts_part{part_num}.csv' with open(part_file, 'w', newline='', encoding='utf-8-sig') as f: f.write(header) f.writelines(current_part) print(f"Часть {part_num} сохранена: {part_file}") # Удаляем временный файл temp_file.unlink() def save(self): if self.split_size_mb > 0: print(f"Разбивка на части по {self.split_size_mb} МБ включена.") if self.format == 'json': self._split_and_save_json(self.posts) elif self.format == 'csv': self._split_and_save_csv(self.posts) else: print(f"Неизвестный формат {self.format}, данные не сохранены.") else: # Без разбивки if self.format == 'json': output_file = self.output_dir / 'posts.json' with open(output_file, 'w', encoding='utf-8') as f: json.dump(self.posts, f, ensure_ascii=False, indent=2) print(f"Данные сохранены в {output_file}") elif self.format == 'csv': output_file = self.output_dir / 'posts.csv' with open(output_file, 'w', newline='', encoding='utf-8-sig') as f: writer = csv.DictWriter(f, fieldnames=['author', 'post_number', 'content']) writer.writeheader() writer.writerows(self.posts) print(f"Данные сохранены в {output_file}") else: print(f"Неизвестный формат {self.format}, данные не сохранены.") def run(self): super().run() self.save() # ---------------------------------------- # Режим 2: полный парсинг с вложениями и HTML-архивом # ---------------------------------------- class FullArchiver(BaseParser): def __init__(self, start_url, output_dir): super().__init__(start_url, output_dir) self.attachment_counter = 0 self.local_attachments = {} # Создаём папки для вложений self.attachments_dir = self.output_dir / 'attachments' self.images_dir = self.attachments_dir / 'images' self.videos_dir = self.attachments_dir / 'videos' self.docs_dir = self.attachments_dir / 'docs' for d in [self.attachments_dir, self.images_dir, self.videos_dir, self.docs_dir]: d.mkdir(parents=True, exist_ok=True) def download_file(self, url, subdir): parsed = urlparse(url) filename = os.path.basename(unquote(parsed.path)) if not filename or '.' not in filename: self.attachment_counter += 1 try: head = self.session.head(url, timeout=5, allow_redirects=True) content_type = head.headers.get('content-type', '') ext = self.guess_extension_by_mime(content_type) filename = f"file_{self.attachment_counter}{ext}" except: filename = f"file_{self.attachment_counter}.bin" else: filename = filename.split('?')[0] base, ext = os.path.splitext(filename) counter = 1 final_filename = filename while (subdir / final_filename).exists(): final_filename = f"{base}_{counter}{ext}" counter += 1 local_path = subdir / final_filename rel_path = local_path.relative_to(self.output_dir).as_posix() try: with self.session.get(url, stream=True, timeout=self.timeout) as r: r.raise_for_status() with open(local_path, 'wb') as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) print(f" Скачан файл: {rel_path}") return rel_path except Exception as e: print(f" Ошибка скачивания {url}: {e}") return None def guess_extension_by_mime(self, mime): mime = mime.lower() if 'image/jpeg' in mime: return '.jpg' if 'image/png' in mime: return '.png' if 'image/gif' in mime: return '.gif' if 'video/mp4' in mime: return '.mp4' if 'application/pdf' in mime: return '.pdf' return '.bin' def is_attachment_url(self, url): if not url: return False if url.startswith('#') or url.startswith('javascript:'): return False path = urlparse(url).path.lower() if any(path.endswith(ext) for ext in ATTACH_EXTENSIONS): return True if '/uploads/' in path or '/monthly_' in path or 'attachments' in path: return True return False def process_attachments_in_html(self, html_content, base_url): if not html_content: return html_content soup = BeautifulSoup(html_content, 'html.parser') for a_tag in soup.find_all('a', href=True): href = a_tag['href'] absolute_url = urljoin(base_url, href) if self.is_attachment_url(absolute_url): if absolute_url in self.local_attachments: local_path = self.local_attachments[absolute_url] else: ext = os.path.splitext(urlparse(absolute_url).path)[1].lower() if ext in IMAGE_EXTENSIONS: subdir = self.images_dir elif ext in VIDEO_EXTENSIONS: subdir = self.videos_dir else: subdir = self.docs_dir local_path = self.download_file(absolute_url, subdir) if local_path: self.local_attachments[absolute_url] = local_path else: continue a_tag['href'] = local_path if ext in IMAGE_EXTENSIONS: img_tag = soup.new_tag('img', src=local_path, alt=local_path, style="max-width:100%;") a_tag.replace_with(img_tag) elif ext in VIDEO_EXTENSIONS: video_tag = soup.new_tag('video', controls=True, style="max-width:100%;") source_tag = soup.new_tag('source', src=local_path, type='video/mp4') video_tag.append(source_tag) a_tag.replace_with(video_tag) for img_tag in soup.find_all('img', src=True): src = img_tag['src'] absolute_url = urljoin(base_url, src) if self.is_attachment_url(absolute_url): if absolute_url in self.local_attachments: local_path = self.local_attachments[absolute_url] else: local_path = self.download_file(absolute_url, self.images_dir) if local_path: self.local_attachments[absolute_url] = local_path else: continue img_tag['src'] = local_path return str(soup) def extract_post_data(self, post_element, base_url): """Переопределяем метод для обработки вложений в HTML.""" author_elem = post_element.select_one('.cAuthorPane_author, .ipsComment_author, .author') if not author_elem: return None author = author_elem.get_text(strip=True) post_id = None if post_element.get('id'): match = re.search(r'(\d+)$', post_element.get('id')) if match: post_id = match.group(1) if not post_id: id_link = post_element.select_one('a[data-commentid]') if id_link and id_link.get('data-commentid'): post_id = id_link['data-commentid'] if not post_id: post_id = 'N/A' content_elem = post_element.select_one('.cPost_contentWrap, .ipsComment_content, .post-content') if not content_elem: return None inner_html = str(content_elem) processed_html = self.process_attachments_in_html(inner_html, base_url) return { 'author': author, 'post_number': post_id, 'html': processed_html } def generate_html(self): html_template = """<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Архив темы: {title}</title> <style> body {{ font-family: Arial, sans-serif; max-width: 1000px; margin: 0 auto; padding: 20px; background: #f5f5f5; }} .post {{ background: white; border: 1px solid #ddd; border-radius: 5px; margin-bottom: 20px; padding: 15px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }} .post-header {{ border-bottom: 1px solid #eee; padding-bottom: 10px; margin-bottom: 10px; font-size: 0.9em; color: #666; }} .post-author {{ font-weight: bold; color: #333; }} .post-id {{ color: #999; margin-left: 10px; }} .post-content {{ line-height: 1.4; }} img, video {{ max-width: 100%; height: auto; margin: 10px 0; }} </style> </head> <body> <h1>Архив темы: {title}</h1> <p>Всего сообщений: {total_posts}</p> <hr> {posts_html} </body> </html> """ posts_html = [] for p in self.posts: posts_html.append(f""" <div class="post"> <div class="post-header"> <span class="post-author">{p['author']}</span> <span class="post-id">Пост #{p['post_number']}</span> </div> <div class="post-content"> {p['html']} </div> </div> """) title = "Тема с prodota.ru" final_html = html_template.format( title=title, total_posts=len(self.posts), posts_html='\n'.join(posts_html) ) return final_html def run(self): super().run() print("Генерация HTML-страницы...") html_content = self.generate_html() index_path = self.output_dir / 'index.html' with open(index_path, 'w', encoding='utf-8') as f: f.write(html_content) print(f"HTML-страница сохранена: {index_path.absolute()}") # ---------------------------------------- # Точка входа: только выбор режима и размера части # ---------------------------------------- if __name__ == '__main__': print("=== Парсер форума prodota.ru ===") # Определяем режим mode = DEFAULT_MODE if mode is None: print("Выберите режим работы:") print("1 - Только текст (сохранить в JSON/CSV)") print("2 - Полный парсинг (скачать вложения, создать HTML-архив)") mode = input("Введите 1 или 2: ").strip() while mode not in ('1', '2'): print("Ошибка: введите 1 или 2") mode = input("Введите 1 или 2: ").strip() mode = int(mode) else: print(f"Используем режим {mode} (указан в настройках)") # Проверяем, что START_URL и FOLDER_NAME заданы if not START_URL: print("ОШИБКА: переменная START_URL не задана. Отредактируйте настройки в начале кода.") exit(1) if not FOLDER_NAME: print("ОШИБКА: переменная FOLDER_NAME не задана. Отредактируйте настройки в начале кода.") exit(1) # Для режима 1 запрашиваем размер разбивки split_size_mb = 0 if mode == 1: print("\nДля текстового режима можно разбить результат на несколько файлов.") split_input = input("Введите максимальный размер части в МБ (0 = не разбивать): ").strip() try: split_size_mb = int(split_input) if split_size_mb < 0: split_size_mb = 0 except: split_size_mb = 0 if split_size_mb > 0: print(f"Будет выполнена разбивка на части по {split_size_mb} МБ.") # Создаём полный путь к папке full_path = os.path.join(DEFAULT_OUTPUT_DIR, FOLDER_NAME) os.makedirs(full_path, exist_ok=True) # Запуск в зависимости от режима if mode == 1: print("\n=== Режим: только текст ===") parser = TextParser(START_URL, full_path, format=TEXT_FORMAT, split_size_mb=split_size_mb) parser.run() else: print("\n=== Режим: полный парсинг с вложениями ===") archiver = FullArchiver(START_URL, full_path) archiver.run() print("\nГотово! Файлы сохранены в папку:", full_path) Цитата moonfangtopich написал 29.08.2019 в 14:57: У вас недостаточно широкий кругозор, пацаны Я странствия этого еблана видел в покерных топанах, а потом в таверне - это один из самых безумных людей на форуме. Я искренне надеялся, что его зов о помощи останется незамеченным, но нет, нашелся доброволец и вот уже три страницы мы пожинаем плоды Поделиться сообщением Ссылка на сообщение
Gomosek #1918 вчера в 19:16 (изменено) Блять да скиньте денег пацану. куда делись эти два криптомилиардера что тут были раньше. Не помню как Ники пишуться Изменено вчера в 19:17 пользователем Gomosek Цитата Поделиться сообщением Ссылка на сообщение
yellyex #1919 вчера в 19:31 Gomosek написал 14 минут назад: Блять да скиньте денег пацану. куда делись эти два криптомилиардера что тут были раньше. Не помню как Ники пишуться Поедешь со мной в свадебное путешествие? 😍💓♥️ Цитата moonfangtopich написал 29.08.2019 в 14:57: У вас недостаточно широкий кругозор, пацаны Я странствия этого еблана видел в покерных топанах, а потом в таверне - это один из самых безумных людей на форуме. Я искренне надеялся, что его зов о помощи останется незамеченным, но нет, нашелся доброволец и вот уже три страницы мы пожинаем плоды Поделиться сообщением Ссылка на сообщение
Qreeq #1920 вчера в 19:39 Ratio написал 36 минут назад: Qreeq написал 44 минуты назад: Еще раз цифру 15к назовешь, я лично приеду тебе ебало бить долбоебу Его там лунтик хуем наказывать собирался. Чем закончилось ? Не могу уснуть, психую опять, зря просрался на форум Цитата Поделиться сообщением Ссылка на сообщение