Парсинг с помощью LLM: зачем, как и сколько стоит?

Во всю идет 2025 год, и нейросети перестают быть чем-то фантастическим. Они уже повсюду в нашей жизни: от умных колонок в квартирах до сложнейших систем, управляющих логистикой и финансами. Вместе с ними стремительно меняется подход к работе с данными. В этой статье мы поговорим о том, как современные LLM помогают автоматизировать сбор данных с веб-сайтов и сводят к минимуму рутинную настройку и «подкручивание» парсеров.

ac822b3e8b8fdab8f0e9dc2957cd1a58.png

Что еще вы найдете в этой статье?

  • Разберемся, как большие языковые модели упрощают процесс парсинга и в каких случаях они особенно эффективны.

  • Обсудим финансовую сторону вопроса и дадим ориентиры по бюджету, чтобы вы смогли понять, подходит ли этот путь именно вам.

  • Обсудим, как и для чего еще можно применять эти подходы на практике.

Для кого эта статья?

  • Для разработчиков и дата-аналитиков, которые хотят расширить свой стек инструментов по сбору данных и повысить скорость разработки парсеров.

  • Для руководителей проектов и бизнесменов, которые хотят оптимизировать затраты на сбор данных и повысить эффективность.

  • Для тех, кто следит за трендами в мире LLM и машинного обучения и хочет увидеть, как эти технологии работают на реальных примерах.

В качестве примеров кода я буду использовать Python. Полный код представленных примеров можно скачать с Github.

Как сейчас мы парсим данные с веб-сайтов

Классический способ собрать информацию с сайта — написать набор скриптов, которые обработают HTML и вытянут нужные фрагменты: текст, ссылки, цены, характеристики, телефоны, почты и т. д. Для этого есть популярные библиотеки вроде requests на python. А для асинхронной работы httpx, aiohttp. Для разбора HTML старый добрый Beutifulsoup. Ну и конечно фреймворки, типа Scrapy. Если сайт рендерит содержимое на стороне клиента с помощью JavaScript, в ход идут Selenium, Playwright или Puppeteer — инструменты, которые позволяют управлять браузером и парсить уже прорендеренную страницу.

Главная идея всех этих подходов — это в явном виде прописать, какие элементы HTML страницы нужно вытащить. Например, чтобы в найти div с классом .product-info или спарсить теги , в которых хранится цена. На помощь приходят XPath и CSS-селекторы, а иногда — регулярные выражения. Например, чтобы в Scrapy спарсить информацию о продукте с помощью CSS или XPath, нужно написать примерно такую конструкцию:

import scrapy

class ExampleSpider(scrapy.Spider):
	name = "example_spider"
	start_url = ["https://example.com/"]

	def parse(self, response):
	# Извлекаем текст информации о продукте с помощью CSS
	product_info = reponse.css("div.product-info::text").get()
	
	# Извлекаем цену, предположим, она находится в 
	product_price = response.css("span.price::text").get()

	yield {
		"product_info": product_info,
		"product_price": product_price
	}

Тоже самое при помощи XPath:

...
# Извлекаем текст информации о продукте при помощи XPath
product_info = response.xpath("//div[@class='product-info']/text()").get()

# Извлекаем цену с XPath
product_price = response.xpath("//span[@class='price']/text()").get()
...

Такой подход отлично работает, но требует постоянной поддержки. Стоит владельцам сайта немного изменить верстку, добавить новые классы или изменить структуру — парсер ломается или собирает некорректные данные.

А что если нужно парсить не один и тот же сайт? Что если нужно собирать данные одновременно с десятков или даже сотен ресурсов? Тут сложности умножаются: набор селекторов, регулярных выражений и дополнительных «костылей» растет в геометрической прогрессии.

Нет ли способа сделать весь этот процесс гибче? Чтобы меняющаяся структура сайтов не ломала скрипты. А обновления верстки отлавливались автоматически. Именно вот здесь, на этих вопросах, все заметнее становятся решения на базе нейросетей.

Делаем запросы к LLM по API

Когда речь заходит о «парсинге с помощью нейросетей», можно представить себе громоздкую историю с обучением моделей, сбором датасетов и сложной инфраструктурой. На деле же ситуация упростилась благодаря готовым моделям, типа GPT. Не нужно «учить» нейронную сеть с нуля — достаточно воспользоваться публичным API, указывая, какой именно результат вы хотите получить. Перейдем к примерам.

Давайте для начала напишем простой запрос к веб-сайту, чтобы получить его структуру HTML. Я буду использовать requests, предварительно установив его.

import requests

def scrape_html(url: str) -> str:
	response = requests.get(url)
	return response.text

Здесь все довольно просто: написали функцию, которая на вход принимает URL документа, делает к нему HTTP-запрос и возвращает HTML целиком. Получили весь HTML-код документа. Теперь нужно передать его модели GPT для обработки.

Я возьму для примера сайт, который специально был создан для обучения парсингу для тех, кто только начинает свой путь, а также, для отладки парсеров более опытных разработчиков. Возможно вы видели и знаете этот сайт: http://books.toscrape.com/.

177f1428eb20b168f3af0ecb9bc02c64.png

На первой странице представлен список книг с названием, ценой, наличием рейтингом и другими параметрами. Для простоты эксперимента я выберу 3 параметра для парсинга: название книги, цена и рейтинг. В качестве модели будет работать GPT-4o.

Итак, пишем обращение к модели по API:

from openai import OpenAI

# здесь должен быть ваш ключ API 
OPENAI_API_KEY = "openai_api_key"

# создание объекта OpenAI
client = OpenAI(api_key=OPENAI_API_KEY)


def extract_info(content: str):
	# прописываем системный промпт
	system_message = {
		"role": "system",
		"content": "Получи цену и рейтинг на все книги со страницы строго в json формате: {book: str, price: float, rating: int}."	
	}
	messages = [system_message]
	# добавляем в промпт HTML-код документа
	messages.append({"role": "user", "content": content})

	# делаем запрос к API
	response = client.chat.completions.create(
		model="gpt-4o",
		messages=messages,
		# формат ответа json
		response_format={"type": "json_object"}
	)

	# возвращаем ответ
	return response.choices[0].message.content

Пояснения к коду выше

Для начала, нужно установить библиотеку openai:

 pip install openai

Далее импортируем оттуда класс OpenAI. Создаем объект этого класса. Здесь понадобится ключ API. Как его получить, подробно написано в этом руководстве: https://vc.ru/ai/1654874-openai-api-kak-ispolzovat-na-praktike-v-seo.

Затем, пишем системный промпт, в котором указываем, какие параметры нужно спарсить со страницы и строго определяем, в каком формате эти данные нужно получить на выходе. Я указываю следующее:

Получи цену и рейтинг на все книги со страницы строго в json формате: {book: str, price: float, rating: int}.

Значение типизации данных и формата ответа

Обратите внимание, что я строго прописал типы выходных данных для каждого параметра: Название книги: строка, цена: число с точкой, рейтинг: целое число. Указывая типы данных в системном промпте (book: str, price: float, rating: int), мы создаем четкую схему, которую модель должна соблюдать. Это решает две важные задачи:

  1. Устраняет двусмысленность интерпретации. Когда цена, например, может вернуться как строка »£51.77».

  2. Работает в связке с response_format={«type»: «json_object»}. response_format — это встроенный атрибут в API OpenAI. Он позволяет получать структурированный JSON, который в дальнейшем можно использовать. А также, такой формат снижает вероятность ошибок и лишних данных, когда модель начинает пояснять свой ответ.

После формирования системного промпта, мы передаем HTML-содержимое страницы в качестве пользовательского сообщения в messages и делаем запрос к API.

Расчет стоимости парсинга с OpenAI API

Перед тем, как получить ответ, давайте напишем функцию, которая будет подсчитывать стоимость нашего парсинга в режиме реального времени. Это критически важно, ведь нам нужно понимать экономическую эффективность применения LLM в сравнении с традиционными парсерами. При масштабировании решения на десятки и сотни страниц, даже небольшая стоимость запроса может вылиться в существенную сумму.

Для точного подсчета токенов используем библиотеку tiktoken, которая применяет тот же алгоритм токенизации, что и API OpenAI. Она позволяет подсчитать количество токенов на input и на output, чтобы в дальнейшем определить общую стоимость.

Простая функция, которая считает количество токенов, модель стандартно передаем gpt-4o.

def count_tokens(text, model="gpt-4o"):
	# Подсчет количества токенов в тексте
	encoding = tiktoken.encoding_for_model(model)
	return len(encoding.encode(text))

И функция, которая вычисляет и возвращает стоимость для input, output и итоговую.

def calculate_cost(input_tokens, output_tokens, model="gpt-4o"):
    # Расчет стоимости запроса на основе количества токенов
    rates = {
        "gpt-4o": {"input": 5, "output": 15},
        "gpt-3.5-turbo": {"input": 0.5, "output": 1.5}
    }
    
    input_cost = input_tokens * rates[model]["input"] / 1_000_000
    output_cost = output_tokens * rates[model]["output"] / 1_000_000
    
    return {
        "input_cost": input_cost,
        "output_cost": output_cost,
        "total_cost": input_cost + output_cost
    }

В rates можно добавить в таком же формате любые модели, чтобы потом передать ее для подсчета стоимости в параметре model функции calculate_cost (). С подробным прайсом на модели OpenAI можно ознакомится на этой странице https://platform.openai.com/docs/pricing.

Запуск парсера и получение результатов

Осталось объединить все и запустить парсер:

URL = "http://books.toscrape.com/"

MODEL = "gpt-4o"

client = OpenAI(api_key=OPENAI_API_KEY)

html_content = scrape_html(URL)
input_tokens = count_tokens(html_content, MODEL)

# Извлечение информации
result = extract_info(html_content, client, MODEL)

# Подсчет выходных токенов
output_tokens = count_tokens(result, MODEL)

# Расчет стоимости
cost = calculate_cost(total_input_tokens, output_tokens, MODEL)

# Отчет о стоимости
print("\n--- ОТЧЕТ О СТОИМОСТИ ПАРСИНГА ---")
print(f"Модель: {MODEL}")
print(f"Входные токены: {input_tokens:,} (${cost['input_cost']:.4f})")
print(f"Выходные токены: {output_tokens:,} (${cost['output_cost']:.4f})")
print(f"ИТОГО: ${cost['total_cost']:.4f}")

# Парсим JSON-ответ
parsed_data = json.loads(result)

# Вывод результатов
print("\n--- РЕЗУЛЬТАТЫ ПАРСИНГА ---")
print(f"Всего книг извлечено: {len(parsed_data['books'])}")
print("\nПример данных (первые 3 книги):")
for i, book in enumerate(parsed_data['books'][:3]):
	print(f"{i+1}. {book['book']} - £{book['price']} - {book['rating']} звезд")
    
# Сохранение результатов в файл
with open("parsed_books.json", "w", encoding="utf-8") as f:
	json.dump(parsed_data, f, ensure_ascii=False, indent=2)

print(f"\nРезультаты сохранены в файл parsed_books.json")

И наконец, давайте посмотрим результаты, которые получились с первого запуска:

9eddf05160f9c61ab05a8b79d05e9b8b.png

Сначала, обратите внимание на результаты парсинга. У меня получился структурированный JSON, который сохранился в файл. Это валидный JSON без единой ошибки.

88ee3f2f8dab989deb7f574d8567a2d9.png

Все типы данных соответствуют тому, что мы хотели. Названия книг, цены, рейтинг — все ОК. Больше всего мне было интересно, как модель справится с парсингом рейтинга книги. Ведь на странице рейтинг книги выводится с помощью CSS соответствующего класса.

ac44678c1973792ca907de8d351de72f.png

Например, если рейтинг книги — 3 звезды, то назначается класс Three, в котором настроено отображение 3 звезд, вот так:

231bed89559a465e49367795aa0cab04.png

Модель на отлично справилась с этой задачей. Она по названию класса перевела все рейтинги в целые числа. В обычном парсере, чтобы решить подобную задачу, нужно писать, как минимум, отдельный обработчик с несколькими if-else. Здесь же мы просто написали строчку: rating: int и на этом все. Это похоже на волшебство! Я постоянно использую нейросети и все равно удивляюсь и радуюсь в такие моменты :).

Стоимость парсинга с применением OpenAI API

Почти 10 тыс. токенов пришло на вход модели, что и составило наибольшую стоимость. Всего для парсинга 1 страницы из 20 книг потратили $0.0602. Если бы нам захотелось спарсить все 50 страниц со списками книг, то в общем мы бы потратили чуть больше $3.

Много это или мало? Ответ зависит от контекста. Так что здесь я предлагаю вам самим поразмышлять и, возможно, написать в комментариях ваши мысли.

Reader от Jina.ai

А теперь мы рассмотрим решение, которое сможет сократить количество входящих токенов, а следовательно, и общую стоимость парсинга. Это продукт jina.ai — Reader. Этот инструмент преобразует HTML в формат, удобный для ввода LLM — формат Markdown. Когда мы передаем полный необработанный HTML, в структуре присутствует большое количество посторонних элементов (разметка, скрипты). Для модели все это не представляет ценности, но влияет на стоимость запроса. Reader очищает страницу от ненужных элементов, предоставляя модели только полезную информацию в удобном для нее формате Markdown.

Все что нужно, это добавить вначале запрашиваемого URL: https://r.jina.ai/ Попробуйте сами проделать это в вашем браузере. Ответ должен получится примерно такой:

88d205555a64e04bbb9406c12c76fa59.png

Давайте попробуем добавить это в код.

html_content = scrape_html("https://r.jina.ai/" + URL)

И посмотрим, что получится.

8c2ba98474040e373e1b4e09a9a2d4a2.png

Количество входящих токенов сократилось в 3 раза: с 10 тыс. до 2.8 тыс.! Очень даже неплохой результат. Итоговая стоимость уменьшилась в 2 раза. Несмотря на то, что в структуре страницы, которую отдает https://r.jina.ai/books.toscrape.com я не нашел рейтинга книг, он все таки сохранился в json файл. Я не знаю как это сработало, но это просто факт :) Скорее всего, данные по рейтингам модель просто придумала и они окажутся неточными, поэтому перед парсингом с reader от jina.ai нужно смотреть, есть ли вероятность того, что данные просто не исчезнут после очистки.

Использование нейросетей для классификации и «умного» извлечения данных

Помимо прямого извлечения конкретных полей (цены, названия, характеристик), нейросети можно применять для более продвинутых задач, например, для классификации и категоризации контента. Допустим, у вас есть список из сотен сайтов, и вам нужно понять, о чем тот или иной ресурс: что это за тематика, присутствует ли там конкретный тип товаров или услуг, есть ли определенные триггерные слова (например, «купить», «доставка», «подписка»).

Вместо того чтобы скачивать весь контент и парсить его вручную, можно отдать LLM лишь часть информации, нужную для принятия решения. К примеру, для определения тематики или типа сайта можно ограничиться только информацией из семантических тегов: <p> <h1-h6> <ul> <ol> <strong> и прочие. Нейросеть попытается на основе этих фрагментов классифицировать сайт. Это сэкономит количество токенов, а значит, снизит итоговые затраты на запрос. Или можно воспользоваться тем же reader от jina.ai.</p><pre><code class="python">def classify_website(html_content: str, client, model="gpt-4o") -> str: system_prompt = { "role": "system", "content": ( "Ты – эксперт по анализу веб-сайтов. " "Определи категорию сайта (например, магазин электроники, блог о путешествиях, " "форум по программированию и т. п.) на основе текста, который я тебе дам. " "Верни название категории одной фразой." ) } messages = [system_prompt, {"role": "user", "content": html_content}] response = client.chat.completions.create( model=model, messages=messages ) return response.choices[0].message.content # Пример использования: # предполагаем, что мы уже сократили HTML и оставили только нужные фрагменты: shortened_html = """ <h1>О нас</h1> <p>Мы занимаемся продажей бытовой техники с бесплатной доставкой по всей стране.</p> <p>Наш интернет-магазин предлагает самые низкие цены на популярные модели холодильников и стиральных машин.</p> """ category = classify_website(shortened_html, client) print("Определенная категория сайта:", category)</code></pre><p>Например, в моей практике была задача: дан список из нескольких тысяч сайтов, связанных с недвижимостью. Нужно было из этого списка найти только сайты-агрегаторы, отсечь интернет-магазины, сайты услуг, информационные сайты и другие. Для этого я просто прогнал каждый сайт через GPT модель, которая четко классифицировала каждый из них. Получилось что-то такое.</p><img src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/065/655/2be/0656552bea6bef6efc00e808d8a984dd.png" alt="0656552bea6bef6efc00e808d8a984dd.png" /><h3>Подведение итогов</h3><p>Использование LLM значительно расширяет горизонты парсинга. Если раньше приходилось вручную «вылавливать» фрагменты HTML, поддерживать армию регулярных выражений и CSS-селекторов, то теперь большие языковые модели берут на себя часть «рутины» и понимают структуру контента в целом.</p><p>Вы можете получить готовый JSON с заранее описанной схемой данных, задав все нужные поля в системном промпте.</p><p>В сложных случаях (например, если сайт рендерится через JavaScript, или структура страницы часто меняется) LLM удается адаптироваться быстрее, чем классические инструменты — без «ломающихся» CSS-селекторов.</p><p>Появились сервисы вроде Jina Reader, которые помогают отчистить HTML от лишних элементов и тем самым уменьшить затраты на запросы к нейросетям.</p><p>Однако <strong>LLM — это не волшебная таблетка</strong> для парсинга. Стоит учитывать стоимость, потому что запросы к нейросети могут быть недешевы, особенно при большом объеме страниц или сложных многоуровневых парсингах. Нужно следить за количеством токенов, возможно, объединять классические инструменты с LLM, чтобы обрабатывать только критические места.</p><p>Никуда не делись ограничения на стороне сайтов. Многие ресурсы имеют систему защиты от массового парсинга, используют капчи, анализируют поведение пользователя. Нейросеть может помочь в понимании структуры контента, но не решает проблему обхода сложных антиспам-систем.</p><p>Все еще существует риск галлюцинаций. LLM иногда может придумывать несуществующие поля или неверные значения, особенно если исходный текст неоднозначен или фрагментарен. Важно тщательно валидировать результаты, сверять их с реальным содержимым страницы.</p><p>Чем больше данных вы передаете модели, тем дороже становится запрос. Поэтому необходимо разумно фильтровать контент, отдавая нейросети <strong>только нужные</strong> блоки.</p><p>Тем не менее, нейросетевой парсинг уже сейчас доказывает свою эффективность там, где нужна гибкость и понимание текста «по смыслу», а не чисто по структуре. Это выводит сбор данных на новый уровень, особенно в проектах, где критична скорость и нет желания или возможности разбираться в бурном потоке изменений верстки.</p><p>Общий вывод: </p><ul><li><p>LLM — сильное подспорье для быстрой автоматизации парсинга, особенно если проект не ограничен в бюджете, а структура сайтов изменчива.</p></li><li><p>Классические инструменты по-прежнему отлично работают там, где нужны массовые запросы с минимальными затратами, и структура сайта понятна и стабильна.</p></li><li><p>Самый мощный подход — это комбинация классических парсеров (для фильтрации HTML, обхода капчи, сбора статических полей) и нейросетей (для извлечения «сложных» данных, аналитики, классификации, «умного» заполнения пропусков).</p></li></ul><p>Конечно, использование LLM не превращает парсинг в волшебную кнопку «Собрать все данные». Тем не менее, если вы грамотно подберете архитектуру решения и будете учитывать указанные выше нюансы, вы добьетесь впечатляющих результатов при вполне разумном контроле стоимости и рисков. Желаю всем удачи в экспериментах с нейросетями и приглашаю обсудить ваши кейсы в комментариях! </p><p>Полный код представленных примеров можно скачать с github<br />Мой телеграм<br />Мой блог на VC</p></div></div></div> <p class="copyrights"><span class="source">© <a target="_blank" rel="nofollow" href="https://habr.com/ru/articles/892954/?utm_source=habrahabr&amp;utm_medium=rss&amp;utm_campaign=892954">Habrahabr.ru</a></span></p> </div> <br> <!--<div align="left"> <script type="text/topadvert"> load_event: page_load feed_id: 12105 pattern_id: 8187 tech_model: </script><script type="text/javascript" charset="utf-8" defer="defer" async="async" src="//loader.topadvert.ru/load.js"></script> </div> <br>--> <div style="padding-left: 20px;"> <!-- PCNews 336x280 --> </div> <!-- comments --> </div> <br class="clearer"/> </div> <br class="clearer"/> <div id="footer-2nd"></div> <div id="footer"> <br/><br/> <ul class="horz-menu"> <li class="about"><a href="/info/about.html" title="О проекте">О проекте</a></li> <li class="additional-menu"><a href="/archive.html" title="Архив материалов">Архив</a> </li> <li class="additional-menu"><a href="/info/reklama.html" title="Реклама" class="menu-item"><strong>Реклама</strong></a> <a href="/info/partners.html" title="Партнёры" class="menu-item">Партнёры</a> <a href="/info/legal.html" title="Правовая информация" class="menu-item">Правовая информация</a> <a href="/info/contacts.html" title="Контакты" class="menu-item">Контакты</a> <a href="/feedback.html" title="Обратная связь" class="menu-item">Обратная связь</a></li> <li class="email"><a href="mailto:pcnews@pcnews.ru" title="Пишите нам на pcnews@pcnews.ru"><img src="/media/i/email.gif" alt="e-mail"/></a></li> <li style="visibility: hidden"> <noindex> <!-- Rating@Mail.ru counter --> <script type="text/javascript"> var _tmr = window._tmr || (window._tmr = []); _tmr.push({id: "93125", type: "pageView", start: (new Date()).getTime()}); (function (d, w, id) { if (d.getElementById(id)) return; var ts = d.createElement("script"); ts.type = "text/javascript"; ts.async = true; ts.id = id; ts.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//top-fwz1.mail.ru/js/code.js"; var f = function () { var s = d.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ts, s); }; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); } })(document, window, "topmailru-code"); </script> <noscript> <div style="position:absolute;left:-10000px;"> <img src="//top-fwz1.mail.ru/counter?id=93125;js=na" style="border:0;" height="1" width="1" alt="Рейтинг@Mail.ru"/> </div> </noscript> <!-- //Rating@Mail.ru counter --> </noindex> </li> </ul> </div> <!--[if lte IE 7]> <iframe id="popup-iframe" frameborder="0" scrolling="no"></iframe> <![endif]--> <!--<div id="robot-image"><img class="rbimg" src="i/robot-img.png" alt="" width="182" height="305" /></div>--> <!--[if IE 6]> <script>DD_belatedPNG.fix('#robot-image, .rbimg');</script><![endif]--> </div> <!--[if lte IE 7]> <iframe id="ie-popup-iframe" frameborder="0" scrolling="no"></iframe> <![endif]--> <div id="footer-adlinks"></div> <noindex> <!--LiveInternet counter--><script type="text/javascript"> document.write("<a rel='nofollow' href='//www.liveinternet.ru/click' "+ "target=_blank><img src='//counter.yadro.ru/hit?t45.6;r"+ escape(document.referrer)+((typeof(screen)=="undefined")?"": ";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth? screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+ ";"+Math.random()+ "' alt='' title='LiveInternet' "+ "border='0' width='1' height='1'><\/a>") </script><!--/LiveInternet--> <!-- Rating@Mail.ru counter --> <script type="text/javascript"> var _tmr = window._tmr || (window._tmr = []); _tmr.push({id: "93125", type: "pageView", start: (new Date()).getTime()}); (function (d, w, id) { if (d.getElementById(id)) return; var ts = d.createElement("script"); ts.type = "text/javascript"; ts.async = true; ts.id = id; ts.src = "https://top-fwz1.mail.ru/js/code.js"; var f = function () {var s = d.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ts, s);}; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); } })(document, window, "topmailru-code"); </script><noscript><div> <img src="https://top-fwz1.mail.ru/counter?id=93125;js=na" style="border:0;position:absolute;left:-9999px;" alt="Top.Mail.Ru" /> </div></noscript> <!-- //Rating@Mail.ru counter --> <!-- Yandex.Metrika counter --> <script type="text/javascript"> (function (d, w, c) { (w[c] = w[c] || []).push(function () { try { w.yaCounter23235610 = new Ya.Metrika({ id: 23235610, clickmap: true, trackLinks: true, accurateTrackBounce: true, webvisor: true, trackHash: true }); } catch (e) { } }); var n = d.getElementsByTagName("script")[0], s = d.createElement("script"), f = function () { n.parentNode.insertBefore(s, n); }; s.type = "text/javascript"; s.async = true; s.src = "https://mc.yandex.ru/metrika/watch.js"; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); } })(document, window, "yandex_metrika_callbacks"); </script> <noscript> <div><img src="https://mc.yandex.ru/watch/23235610" style="position:absolute; left:-9999px;" alt=""/> </div> </noscript> <!-- /Yandex.Metrika counter --> <!-- Default Statcounter code for PCNews.ru https://pcnews.ru--> <script type="text/javascript"> var sc_project=9446204; var sc_invisible=1; var sc_security="14d6509a"; </script> <script type="text/javascript" src="https://www.statcounter.com/counter/counter.js" async></script> <!-- End of Statcounter Code --> <script> (function (i, s, o, g, r, a, m) { i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () { (i[r].q = i[r].q || []).push(arguments) }, i[r].l = 1 * new Date(); a = s.createElement(o), m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m) })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'); ga('create', 'UA-46280051-1', 'pcnews.ru'); ga('send', 'pageview'); </script> <script async="async" src="/assets/uptolike.js?pid=49295"></script> </noindex> <!--<div id="AdwolfBanner40x200_842695" ></div>--> <!--AdWolf Asynchronous Code Start --> <script type="text/javascript" src="https://pcnews.ru/js/blockAdblock.js"></script> <script type="text/javascript" src="/assets/jquery.min.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/jquery/jquery.json.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/jquery/jquery.form.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/jquery/jquery.easing.1.2.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/jquery/effects.core.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/js/browser-sniff.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/js/scripts.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/js/pcnews-utils.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/js/pcnews-auth.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/js/pcnews-fiximg.js"></script> <script type="text/javascript" src="/assets/a70a9c7f/js/pcnews-infobox.js"></script> </body> </html>