Мы неоднократно рассказывали о библиотеках и фреймворках, которые ускоряют разработку парсеров, например, для Python, Java и Golang. Существуют разные подходы — от простейших HTTP-клиентов, которые умеют читать только «голый» HTML, до максимально сложных алгоритмов, которые включают в себя компьютерное зрение и помощь искусственного интеллекта (ИИ). В этом материале расскажем о наиболее продвинутых фреймворках для интеграции больших языковых моделей (LLM) в ваши парсеры — LangChain vs LangGraph.
Напомним, ИИ бывает разным. Нейросети, которые работают с текстовым содержимым, называются LLM. Они умеют не только генерировать текст или давать краткие ответы по существу, но и выполнять простые задания: анализировать текст из документов и выдавать по нему краткую справку, изучать содержимое HTML-кода и извлекать конкретное содержимое, а также многое другое. Нас, как можно догадаться из контекста, интересует всё, что связано с парсингом.
Многие современные нейросети работают в виде общедоступных web-сервисов и имеют свой API-интерфейс. Отдельные нейросети уже обзавелись возможностью обработки документов и файлов, включая изображения, презентации, PDF, аудио, видео и пр. Но, в любом случае, при работе по API они имеют свои ограничения. Основная проблема — токенизация. Условно: каждый новый запрос LLM воспринимает как новый (без учёта истории обращений). А так как объём запроса лимитирован неким количеством токенов (токены выступают скорее в роли слов, хотя алгоритм их расчёта выглядит немного сложнее). В итоге получается, что при отправке большого запроса к LLM нужно:
За это отвечают так называемые чанки (в англ. chains), то есть цепочки запросов.
Для удобства автоматизации работы с цепочками запросов нужен специальный софт или библиотеки. И вот тут мы подходим к потребности в LangChain и LangGraph
LangChain— это фреймворк для создания цепочек (chains) вызовов языковых моделей и интеграции их с внешними инструментами: базами данных, парсерами, API и т.п.
На текущий моменте LangChain реализован в виде самостоятельных библиотек (для языков программирования Python, JavaScript и TypeScript), а также в виде готовой платформы (web-сервиса, который работает по API, имеет все необходимые интеграции и готовые инструменты для оркестрации и оценивания — в надёжном облаке, удобном для корпоративного применения).
Основные возможности (функционал) LangChain:
Если упростить ещё, то LangChain — это минимальная база для продвинутой интеграции LLM в свои скрипты и программы. Например, на её основе создаются более сложные решения, в том числе и с использованием систем оркестрации, таких как LangGraph.
LangGraph — это фреймворк для быстрого и удобного проектирования агентов LangChain. Именно LangGraph берёт на себя всё, что связано с созданием точек входа и выхода, проектированием фоновых задач, контролем состояний, масштабированием и отказоустойчивостью.
Грубо говоря, это готовая реализация типовых агентов на базе существующих LLM, которые быстро можно перенастроить под себя или под нужды своих проектов. В итоге можно сосредоточиться не на написании всего с нуля, а только на конфигурировании логики.
Как и LangChain, библиотека LangGraph распространяется по модели с исходным кодом, по лицензии MIT.
Не стоит путать фреймворк LangGraph и платформу LangGraph, Платформа — это уже готовая облачная инфраструктура со своими подписками и тарифами. Она имеет закрытый исходный код.
Специально для удобного визуального проектирования логики LLM-агентов предоставляется среда разработки (IDE-система) — LangGraph Studio. Она предназначена для установки на ПК. В коммерческой версии платформы LangGraph есть облачная реализация LangGraph Studio.
Итак, LangChain — это фреймворк для интеграции LLM в свои скрипты и программы, некая база, с которой может начаться разработка сложных цепочек обмена данными. LangChain выступает в роли прослойки, отвечающей за подключение LLM.
А LangGraph — это инструмент для проектирования LLM-агентов, технически это тоже фреймворк. Он работает поверх LangChain и позволяет быстрее запускать типовые задачи. Самая главная функция — оркестрация большого числа ИИ-агентов.
Технические различия LangChain vs LangGraph:
В итоге, если вам нужно только подключить LLM и организовать разбивку больших объёмов данных на цепочки, то стоит использовать LangChain.
Если вам нужно быстро и точно спроектировать своего LLM-агента или большое число таких агентов (с оркестрацией), то тут уже логично задействовать LangGraph.
Библиотека LangChain сама по себе ничего не парсит. Она отвечает за взаимодействие с нейросетями. А вот нейросети в свою очередь можно привлечь к задачам извлечения данных, Например, для поиска закономерностей (выявления CSS-классов, идентификаторов и специфических атрибутов, помогающих вычленить нужный HTML-элемент и его содержимое), распознавания изображений, их обработки (в том числе для поиска образов и объектов на картинках/видео), транскрибации аудио и т.п.
Предметные примеры ИИ-скраперов в материале про ИИ скрапинг.
Возможности LangChain скрапинга:
Ограничения LangChain скрапинга:
LangChain позволяет стандартизировать синтаксис обращения к LLM. Специально для этого из коробки предлагаются: готовые пакеты интеграции, базовые абстракции (langchain-core), цепочки, агенты и инструменты (tools), отвечающие за построение когнитивной архитектуры вашего приложения.
К инструментам, которые облегчают процесс парсинга через LangChain, можно отнести:
Так как LangChain не работает с web-сайтами напрямую, ему не нужны прокси. Но если вы пишите комплексный парсер, то ему однозначно потребуются прокси. Дело в том, что многие целевые сайты активно защищаются от ботов и автоматического трафика. Чтобы обойти их защиту, могут потребоваться разные средства и подходы. Ротируемые прокси с точным геотаргетингом — одно из самых надёжных средств, которое может работать в тесной связке с другими.
Самый логичный подход — управлять прокси на уровне HTTP-клиента, которым вы пользуетесь для подключения к целевым сайтам. Например, если вы работаете в среде Node.js, то вам нужно настроить прокси для node-fetch. Если работаете через антидетект-браузер или через headless-браузер, то прокси нужно установить для них (с помощью плагинов или специальных переменных/API).
Вполне дееспособный скрипт парсинга на языке Python. Он обеспечивает настройку и работу LangChain через прокси-сервер:
import sqlite3import jsonimport timefrom selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsfrom langchain.llms import OpenAIfrom langchain.agents import initialize_agent, Tool, AgentType# -------------------------------# Настройка базы данных SQLite# -------------------------------conn = sqlite3.connect("products.db")cursor = conn.cursor()cursor.execute('''CREATE TABLE IF NOT EXISTS products (id INTEGER PRIMARY KEY AUTOINCREMENT,url TEXT,title TEXT,price TEXT,description TEXT)''')conn.commit()# -------------------------------# Настройка Selenium с прокси# -------------------------------chrome_options = Options()chrome_options.add_argument("--headless")proxy = "http://username:password@your_proxy_ip:port" # Если без логина: "http://ip:port"chrome_options.add_argument(f'--proxy-server={proxy}')driver = webdriver.Chrome(options=chrome_options)# -------------------------------# Настройка LLM# -------------------------------llm = OpenAI(model_name="gpt-4o", temperature=0)# -------------------------------# Функция для парсинга HTML через LLM# -------------------------------def extract_product_data(html_content: str) -> str:prompt = f"""Вот HTML содержимое страницы товара:{html_content}Вытащи из него название товара, цену и описание. Отдай ответ строго в формате JSON, например:Отвечай только JSON без лишнего текста."""response = llm(prompt)return response# -------------------------------# Описание инструмента для агента# -------------------------------extract_tool = Tool(name="ExtractProductData",func=extract_product_data,description="Извлекает название, цену и описание товара из HTML страницы и возвращает JSON")# -------------------------------# Инициализация агента# -------------------------------agent = initialize_agent(tools=[extract_tool],llm=llm,agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,verbose=True)# -------------------------------# Функция парсинга страницы# -------------------------------def parse_product(url):driver.get(url)time.sleep(3) # Ждём рендер, в секундахhtml = driver.page_source# Запрос к агентуquery = f"Используй инструмент ExtractProductData, чтобы извлечь данные о товаре из этого HTML: {html}"response = agent.run(query)try:data = json.loads(response)title = data.get("title", "")price = data.get("price", "")description = data.get("description", "")except json.JSONDecodeError:print(f"JSON parsing error for {url}")return None# Сохраняем в БДcursor.execute('INSERT INTO products (url, title, price, description) VALUES (?, ?, ?, ?)', (url, title, price, description))conn.commit()print(f"Data saved for page: {url}")return data# -------------------------------# Список страниц для парсинга# -------------------------------urls = ["https://example.com/product/1","https://example.com/product/2",# Добавьте свои URL]for u in urls:parse_product(u)# -------------------------------# Завершаем работу# -------------------------------driver.quit()conn.close()Этот скрипт последовательно обходит список целевых страниц с задействованием прокси и headless-браузера через веб-драйвер Selenium. HTML-код страниц передаётся на анализ в LLM, а та, в соответствии с промтом, возвращает ответ в JSON-формате. Со страниц извлекаются названия товаров, их цена и описание. Данные сохраняются в базу SQlite.
LangGraph работает в паре с LangChain. Это своего рода настройка, которая облегчает построение сложных ИИ-агентов.
Как и в случае с LangChain, прокси в LangGraph не работают из коробки. Их нужно добавлять только на уровне HTTP-клиентов (приложений и библиотек, которые отвечают за подключение к целевым сайтам):
Пример кода на Python — парсинг с LangGraph через прокси:
import requestsimport randomfrom langgraph.graph import StateGraph, END# --- Состояние, которое передаётся между узлами ---class ScraperState:def __init__(self, url="", html="", proxy_used=""):self.url = urlself.html = htmlself.proxy_used = proxy_used# --- Список прокси для ротации ---proxy_list = ["http://user:pass@ip1:port","http://user:pass@ip2:port","http://user:pass@ip3:port",]# --- Узел LangGraph: запрос страницы через прокси ---def fetch_page_with_proxy(state: ScraperState):# Выбираем случайный проксиproxy = random.choice(proxy_list)proxies = {"http": proxy,"https": proxy,}try:print(f"Using proxy: {proxy}")response = requests.get(state.url, proxies=proxies, timeout=10)state.html = response.textstate.proxy_used = proxyexcept Exception as e:print(f"Request error with proxy {proxy}: {e}")state.html = ""state.proxy_used = proxyreturn state# --- Создаём граф ---graph = StateGraph(ScraperState)graph.add_node("fetch_with_proxy", fetch_page_with_proxy)graph.set_entry_point("fetch_with_proxy")graph.add_edge("fetch_with_proxy", END)compiled_graph = graph.compile()# --- Запуск графа ---start_state = ScraperState(url="https://example.com")final_state = compiled_graph.invoke(start_state)print("Final HTML snippet:", final_state.html[:500])print("Proxy used:", final_state.proxy_used)Пара слов о логике работы скрипта с ротацией прокси в LangGraph:
Итак, можно заметить, что ни LangGraph, на LangChain не умеют работать с прокси. Всё из-за того, что эти библиотеки не умеют обращаться к сайтам и веб-ресурсам напрямую. Им обязательно нужны посредники. Их фишка — работа с нейросетями и LLM. И здесь они действительно повышают продуктивность, особенно если речь о сложной архитектуре или о большом количестве LLM.
Этот фреймворк идеально подходит для реализации прослойки, отвечающей за подключение и «общение» в любыми нейросетями. В наборе её возможностей масса мелких профильных инструментов, которые вы получаете в режиме одного окна. Нужно посчитать токены, разбить на чанки, задать разные промты для разных задач? Без проблем.
Но LangChain — это «база», поэтому с ней удобно работать только по линейным сценариям парсинга.
Этот фреймворк дополняет LangChain и облегчает создание кастомных условий, переходов и циклов между разными сценариями и узлами. Соответственно, в LangGraph можно описать (или спроектировать) максимально сложный парсер.
И LangGraph, и LangChain могут использоваться в вашем проекте параллельно. Более того, тот же разработчик предлагает ряд вспомогательных продуктов, но уже на коммерческой основе — это LangSmith и LangGraph Platform (готовая облачная платформа).
Парсинг становится сложнее и часто требует участия ИИ/нейросетей. Чтобы не писать своих коннекторов и не запутаться в синтаксисе отдельных внешних сервисов, можно воспользоваться слоем абстракции, который реализуется фреймворком LangChain. Он облегчает взаимодействие с 600+ внешними инструментами: векторные хранилища, базы данных, системы кеширования и т.п. Но самый главный элемент — LLM (большие языковые модели).
Если вам нужно что-то большее, чем линейные скрипты обработки цепочек запросов, то можно добавить в свой парсер фреймворк LangGraph. Он отвечает за создание графов и позволяет выстраивать сложные многоуровневые рабочие процессы с разными условиями переходов и циклами.
Нельзя сказать, что в сравнении LangChain vs LangGraph кто-то будет лучше. У каждой библиотеки своя сфера применения.
Ни LangChain, ни LangGraph не умеют работать с прокси. Всё из-за того, что у них нет интерфейса для прямого обращения к веб-ресурсам.
Тем не менее, прокси критически необходимы любому парсеру. Как и с помощью чего интегрировать прокси в LangChain или в LangGraph мы рассказали выше.