一架梯子,一头程序猿,仰望星空!
LangChain教程(Python版本) > 内容正文

基于LangChain实现AI爬虫,爬取网页内容


应用案例

网络信息分析是LLM应用中的杀手级应用之一:

  • 用户们将其列为其最想要的AI工具之一。
  • 类似gpt-researcher的开源代码库越来越受欢迎。

图片描述

概述

从网络爬取内容的一些关键步骤如下:

  • 搜索:查询URL(例如使用GoogleSearchAPIWrapper)。
  • 加载:将URL转换成HTML(例如使用AsyncHtmlLoaderAsyncChromiumLoader等)。
  • 转换:将HTML转换为格式化文本(例如使用HTML2TextBeautiful Soup)。

快速开始

pip install -q openai langchain playwright beautifulsoup4
playwright install

使用Chromium的无头实例来爬取HTML内容。

  • 使用Python的asyncio库来处理异步的爬取过程。
  • 使用Playwright来实际与网页进行交互。
from langchain.document_loaders import AsyncChromiumLoader
from langchain.document_transformers import BeautifulSoupTransformer

loader = AsyncChromiumLoader(["https://www.wsj.com"])
html = loader.load()

API参考:

从HTML内容中抓取像<p><li><div><a>标签这样的文本内容:

  • <p>:段落标签。定义HTML中的一个段落,用于将相关的句子和/或短语分组在一起。
  • <li>:列表项标签。用于在有序列表(<ol>)和无序列表(<ul>)中定义列表中的单个项目。
  • <div>:分割标签。是一个块级元素,用于分组其他行内或块级元素。
  • <a>:链接标签。用于定义超链接。
  • <span>:行内容器,用于标记文本或文档的一部分。

对于许多新闻网站(例如WSJ、CNN),标题和摘要都位于<span>标签中。

bs_transformer = BeautifulSoupTransformer()
docs_transformed = bs_transformer.transform_documents(html, tags_to_extract=["span"])
docs_transformed[0].page_content[0:500]
    'English EditionEnglish中文 (Chinese)日本語 (Japanese) More Other Products from WSJBuy Side from WSJWSJ ShopWSJ Wine Other Products from WSJ Search Quotes and Companies Search Quotes and Companies 0.15% 0.03% 0.12% -0.42% 4.102% -0.69% -0.25% -0.15% -1.82% 0.24% 0.19% -1.10% About Evan His Family Reflects His Reporting How You Can Help Write a Message Life in Detention Latest News Get Email Updates Four Americans Released From Iranian Prison The Americans will remain under house arrest until they are '

这些Documents现在已经准备好在各种LLM应用中使用,如下所述。

Loader

AsyncHtmlLoader

AsyncHtmlLoader使用aiohttp库进行异步的HTTP请求,适用于简单和轻量级的爬取。

AsyncChromiumLoader(异步Chromium加载器)

AsyncChromiumLoader使用Playwright启动一个Chromium实例,可以处理JavaScript渲染和更复杂的网页交互。

Chromium是Playwright支持的浏览器之一,Playwright是一个用于控制浏览器自动化的库。

无头模式意味着浏览器在没有图形用户界面的情况下运行,这常用于网络爬虫。

from langchain.document_loaders import AsyncHtmlLoader
urls = ["https://www.espn.com","https://lilianweng.github.io/posts/2023-06-23-agent/"]
loader = AsyncHtmlLoader(urls)
docs = loader.load()

API参考:

HTML2Text(HTML转文本)

HTML2Text将HTML内容直接转换为纯文本(带有类似markdown的格式),而无需对特定标签进行处理。

它最适用于需要提取易读文本而无需处理特定HTML元素的场景。

Beautiful Soup(美丽汤)

Beautiful Soup提供了对HTML内容的更精细的控制,可以提取、删除特定标签和清理内容。

它适用于您想提取特定信息并根据需要清理HTML内容的情况。

from langchain.document_loaders import AsyncHtmlLoader
urls = ["https://www.espn.com", "https://lilianweng.github.io/posts/2023-06-23-agent/"]
loader = AsyncHtmlLoader(urls)
docs = loader.load()

API参考:

    Fetching pages: 100%|#############################################################################################################| 2/2 [00:00
from langchain.document_transformers import Html2TextTransformer
html2text = Html2TextTransformer()
docs_transformed = html2text.transform_documents(docs)
docs_transformed[0].page_content[0:500]

API参考:

    "跳转到主内容 跳转到导航 \n\n\n\n菜单\n\n## ESPN\n\n  * 搜索\n\n  *   * 得分\n\n  * NFL\n  * MLB\n  * NBA\n  * NHL\n  * 足球\n  * NCAAF\n  * …\n\n    * 女子世界杯\n    * LLWS\n    * NCAAM\n    * NCAAW\n    * 体育博彩\n    * 拳击\n    * CFL\n    * NCAA\n    * 板球\n    * F1\n    * 高尔夫\n    * 马\n    * MMA\n    * NASCAR\n    * NBA G League\n    * 奥运会\n    * PLL\n    * 赛车\n    * RN BB\n    * RN FB\n    * 橄榄球\n    * 网球\n    * WNBA\n    * WWE\n    * X Games\n    * XFL\n\n  * 更多"

使用提取进行网络爬虫​

使用函数调用的LLM(语言模型)​

网络爬虫具有许多挑战。

其中之一是现代网站布局和内容的变化性,需要修改爬取脚本以适应这些变化。

使用函数(例如OpenAI)与提取链,我们避免了在网站变化时不断修改代码的情况。

我们使用gpt-3.5-turbo-0613来确保可以访问OpenAI Functions功能(尽管在撰写本文时可能已对所有人开放)。

我们还将temperature保持在0,以降低LLM的随机性。

from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")

API参考:

定义模式

首先,你需要定义一个模式来指定你想要提取的数据的类型。

在这里,键名很重要,因为它们告诉LLM你想要的是什么类型的信息。

所以,要尽可能详细。

在这个例子中,我们只想从华尔街日报网站爬取新闻文章的标题和摘要。

from langchain.chains import create_extraction_chain

schema = {
    "properties": {
        "news_article_title": {"type": "string"},
        "news_article_summary": {"type": "string"},
    },
    "required": ["news_article_title", "news_article_summary"],
}

def extract(content: str, schema: dict):
    return create_extraction_chain(schema=schema, llm=llm).run(content)

API参考:

使用BeautifulSoup运行网络爬虫

如上所示,我们将使用BeautifulSoupTransformer

import pprint
from langchain.text_splitter import RecursiveCharacterTextSplitter

def scrape_with_playwright(urls, schema):

    loader = AsyncChromiumLoader(urls)
    docs = loader.load()
    bs_transformer = BeautifulSoupTransformer()
    docs_transformed = bs_transformer.transform_documents(docs,tags_to_extract=["span"])
    print("Extracting content with LLM")

    splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000, 
                                                                    chunk_overlap=0)
    splits = splitter.split_documents(docs_transformed)

    extracted_content = extract(
        schema=schema, content=splits[0].page_content
    )
    pprint.pprint(extracted_content)
    return extracted_content

urls = ["https://www.wsj.com"]
extracted_content = scrape_with_playwright(urls, schema=schema)

API 参考:

    Extracting content with LLM
    [{'news_article_summary': 'The Americans will remain under house arrest until '
                              'they are allowed to return to the U.S. in coming '
                              'weeks, following a monthslong diplomatic push by '
                              'the Biden administration.',
      'news_article_title': 'Four Americans Released From Iranian Prison'},
     {'news_article_summary': 'Price pressures continued cooling last month, with '
                              'the CPI rising a mild 0.2% from June, likely '
                              'deterring the Federal Reserve from raising interest '
                              'rates at its September meeting.',
      'news_article_title': 'Cooler July Inflation Opens Door to Fed Pause on '
                            'Rates'},
     {'news_article_summary': 'The company has decided to eliminate 27 of its 30 '
                              'clothing labels, such as Lark & Ro and Goodthreads, '
                              'as it works to fend off antitrust scrutiny and cut '
                              'costs.',
      'news_article_title': 'Amazon Cuts Dozens of House Brands'},
     {'news_article_summary': 'President Biden’s order comes on top of a slowing '
                              'Chinese economy, Covid lockdowns and rising '
                              'tensions between the two powers.',
      'news_article_title': 'U.S. Investment Ban on China Poised to Deepen Divide'},
     {'news_article_summary': 'The proposed trial date in the '
                              'election-interference case comes on the same day as '
                              'the former president’s not guilty plea on '
                              'additional Mar-a-Lago charges.',
      'news_article_title': 'Trump Should Be Tried in January, Prosecutors Tell '
                            'Judge'},
     {'news_article_summary': 'The CEO who started in June says the platform has '
                              '“an entirely different road map” for the future.',
      'news_article_title': 'Yaccarino Says X Is Watching Threads but Has Its Own '
                            'Vision'},
     {'news_article_summary': 'Students foot the bill for flagship state '
                              'universities that pour money into new buildings and '
                              'programs with little pushback.',
      'news_article_title': 'Colleges Spend Like There’s No Tomorrow. ‘These '
                            'Places Are Just Devouring Money.’'},
     {'news_article_summary': 'Wildfires fanned by hurricane winds have torn '
                              'through parts of the Hawaiian island, devastating '
                              'the popular tourist town of Lahaina.',
      'news_article_title': 'Maui Wildfires Leave at Least 36 Dead'},
     {'news_article_summary': 'After its large armored push stalled, Kyiv has '
                              'fallen back on the kind of tactics that brought it '
                              'success earlier in the war.',
      'news_article_title': 'Ukraine Uses Small-Unit Tactics to Retake Captured '
                            'Territory'},
     {'news_article_summary': 'President Guillermo Lasso says the Aug. 20 election '
                              'will proceed, as the Andean country grapples with '
                              'rising drug gang violence.',
      'news_article_title': 'Ecuador Declares State of Emergency After '
                            'Presidential Hopeful Killed'},
     {'news_article_summary': 'This year’s hurricane season, which typically runs '
                              'from June to the end of November, has been '
                              'difficult to predict, climate scientists said.',
      'news_article_title': 'Atlantic Hurricane Season Prediction Increased to '
                            '‘Above Normal,’ NOAA Says'},
     {'news_article_summary': 'The NFL is raising the price of its NFL+ streaming '
                              'packages as it adds the NFL Network and RedZone.',
      'news_article_title': 'NFL to Raise Price of NFL+ Streaming Packages as It '
                            'Adds NFL Network, RedZone'},
     {'news_article_summary': 'Russia is planning a moon mission as part of the '
                              'new space race.',
      'news_article_title': 'Russia’s Moon Mission and the New Space Race'},
     {'news_article_summary': 'Tapestry’s $8.5 billion acquisition of Capri would '
                              'create a conglomerate with more than $12 billion in '
                              'annual sales, but it would still lack the '
                              'high-wattage labels and diversity that have fueled '
                              'LVMH’s success.',
      'news_article_title': "Why the Coach and Kors Marriage Doesn't Scare LVMH"},
     {'news_article_summary': 'The Supreme Court has blocked Purdue Pharma’s $6 '
                              'billion Sackler opioid settlement.',
      'news_article_title': 'Supreme Court Blocks Purdue Pharma’s $6 Billion '
                            'Sackler Opioid Settlement'},
     {'news_article_summary': 'The Social Security COLA is expected to rise in '
                              '2024, but not by a lot.',
      'news_article_title': 'Social Security COLA Expected to Rise in 2024, but '
                            'Not by a Lot'}]

我们可以将抓取到的标题与页面进行比较:

图像描述

通过查看LangSmith跟踪,我们可以了解到底层发生了什么:

  • 它遵循了在抽取中所解释的内容。
  • 我们在输入文本上调用了information_extraction函数。
  • 它将尝试从url内容填充提供的模式。

研究自动化

在网络爬取方面,我们可能希望使用搜索内容来回答特定问题。

我们可以使用检索器(retriever)来自动化网络研究的过程,例如 WebResearchRetriever文档)。

图片描述

从这里复制要求:点击这里

pip install -r requirements.txt

设置 GOOGLE_CSE_IDGOOGLE_API_KEY

from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.chat_models.openai import ChatOpenAI
from langchain.utilities import GoogleSearchAPIWrapper
from langchain.retrievers.web_research import WebResearchRetriever

API 参考:

vectorstore = Chroma(embedding_function=OpenAIEmbeddings(),persist_directory="./chroma_db_oai")

llm = ChatOpenAI(temperature=0)

search = GoogleSearchAPIWrapper()

通过上述工具初始化检索器,可以完成以下操作:

  • 使用一个LLM生成多个相关的搜索查询(一个LLM调用)
  • 执行每个查询的搜索
  • 选择每个查询的前K个链接(多个并行搜索调用)
  • 加载所选择链接的信息(并行爬取页面)
  • 将这些文档索引到一个向量存储中
  • 找到每个原始生成的搜索查询的最相关文档
web_research_retriever = WebResearchRetriever.from_llm(
    vectorstore=vectorstore,
    llm=llm,
    search=search)
import logging
logging.basicConfig()
logging.getLogger("langchain.retrievers.web_research").setLevel(logging.INFO)
from langchain.chains import RetrievalQAWithSourcesChain
user_input = "LLM如何驱动自主代理工作?"
qa_chain = RetrievalQAWithSourcesChain.from_chain_type(llm,retriever=web_research_retriever)
result = qa_chain({"question": user_input})
result

API 参考文档:

    INFO:langchain.retrievers.web_research:为谷歌搜索生成问题 ...
    INFO:langchain.retrievers.web_research:谷歌搜索的问题(原始数据):{'question': 'LLM动力自主代理如何工作?', 'text': LineList(lines=['1. LLM动力自主代理的工作原理是什么?\n', '2. LLM动力自主代理如何操作?\n'])}
    INFO:langchain.retrievers.web_research:谷歌搜索的问题:['1. LLM动力自主代理的工作原理是什么?\n', '2. LLM动力自主代理如何操作?\n']
    INFO:langchain.retrievers.web_research:搜索相关的网址 ...
    INFO:langchain.retrievers.web_research:搜索相关的网址 ...
    INFO:langchain.retrievers.web_research:搜索结果:[{'title': 'LLM动力自主代理 | 黑客新闻', 'link': 'https://news.ycombinator.com/item?id=36488871', 'snippet': '2023年6月26日 ... 正确。 温度为0表示始终选择最高概率的词元(即“max”函数),而温度为1表示您\xa0...'}]
    INFO:langchain.retrievers.web_research:搜索相关的网址 ...
    INFO:langchain.retrievers.web_research:搜索结果:[{'title': 'LLM动力自主代理 | Lil'Log', 'link': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'snippet': '2023年6月23日 ... 基于LLM的简单提示,可以将任务分解为较小的子目标,并且还可以通过回顾和改进先前的经验来反思和完善其操作。内存分为短期记忆用于上下文学习,和长期记忆用于在较长时间内保留和回忆信息。工具使用涉及代理调用外部API获取额外信息。这些代理已经在各种应用中使用,包括科学发现和生成代理模拟。'}]
    INFO:langchain.retrievers.web_research:要加载的新网址:[]
    INFO:langchain.retrievers.web_research:从网址中获取最相关的信息...



    {'question': 'LLM动力自主代理如何工作?',
     'answer': 'LLM动力自主代理通过使用LLM作为代理的大脑,同时辅以计划、记忆和工具使用等多个关键组件来工作。在规划方面,代理将大型任务拆分为较小的子目标,并根据过去的经验来反思和完善其操作。记忆分为短期记忆,用于上下文学习,和长期记忆,允许代理在较长时间内保留和回忆信息。工具使用涉及代理调用外部API获取额外信息。这些代理已经在包括科学发现和生成代理模拟在内的各种应用中使用。',
     'sources': ''}

进一步了解

  • 这是一个应用程序,用于使用轻量级用户界面包装此检索器。