AI爬虫?爬!

1.你是否还在为大模型的key而感到忧伤和囊中羞涩,openrouter.ai,目前可免费白嫖多个大模型,代码如下

from openai import OpenAIclient = OpenAI(base_url="https://openrouter.ai/api/v1",api_key="",
)completion = client.chat.completions.create(extra_headers={"HTTP-Referer": "<YOUR_SITE_URL>", # Optional. Site URL for rankings on openrouter.ai."X-Title": "<YOUR_SITE_NAME>", # Optional. Site title for rankings on openrouter.ai.},extra_body={},model="google/gemini-2.5-pro-exp-03-25:free",messages=[{"role": "user","content": [{"type": "text","text": "What is in this image?"},{"type": "image_url","image_url": {"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"}}]}]
)
print(completion.choices[0].message.content)

2.然后是爬虫代码(下面这段代码就是实现的官网的功能Playground - Firecrawl)

# Install with pip install firecrawl-py(https://docs.firecrawl.dev/api-reference/endpoint/crawl-post)官网登录获得key
from firecrawl import FirecrawlAppapp = FirecrawlApp(api_key='')response = app.scrape_url(url='https://docs.cline.bot/', params={'formats': [ 'markdown' ],
})
print(response)

3.还有一个用上面免费的大模型来进行对网页的分析

import os
from firecrawl import FirecrawlApp
import json
import re
import requests
from requests.exceptions import RequestException
from dotenv import load_dotenv
from openai import OpenAI# Load environment variables
load_dotenv()# Retrieve API keys from environment variables
firecrawl_api_key = os.getenv("FIRECRAWL_API_KEY")
openrouter_api_key = os.getenv("OPENROUTER_API_KEY")# Initialize the FirecrawlApp and OpenAI client
app = FirecrawlApp(api_key=firecrawl_api_key)
client = OpenAI(base_url="https://openrouter.ai/api/v1",api_key=openrouter_api_key,
)model_name = "google/gemini-2.5-pro-exp-03-25:free"# ANSI color codesclass Colors:CYAN = '\033[96m'YELLOW = '\033[93m'GREEN = '\033[92m'RED = '\033[91m'MAGENTA = '\033[95m'BLUE = '\033[94m'RESET = '\033[0m'def extract_urls_from_markdown(markdown_text):pattern = r'(https?://[^\s\'")]+)'found = re.findall(pattern, markdown_text)return list(set(found))def detect_mime_type(url, timeout=8):try:resp = requests.head(url, timeout=timeout, allow_redirects=True)ctype = resp.headers.get('Content-Type', '').lower()exts = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.heic', '.heif']if 'pdf' in ctype:return 'pdf'elif ctype.startswith('image/') and any(url.lower().endswith(ext) for ext in exts):return 'image'else:return Noneexcept RequestException as e:print(f"Warning: HEAD request failed for {url}. Error: {e}")return Nonedef query_openai(content):response = client.chat.completions.create(extra_headers={"HTTP-Referer": "https://your-site.com","X-Title": "YourSiteName",},model=model_name,messages=[{"role": "user", "content": content}],)print("response",response)return response.choices[0].message.content.strip()def extract_json_from_response(text):# 兼容含 markdown 和纯 jsonmatch = re.search(r"```json\s*(.*?)```", text, re.DOTALL)if not match:match = re.search(r"```(.*?)```", text, re.DOTALL)  # 兜底,兼容没有指定json的codeblockif match:json_str = match.group(1).strip()else:json_str = text.strip()print("=== Extracted JSON Content ===")print(json_str)return json.loads(json_str)return json.loads(json_str)
def find_relevant_page_via_map(objective, url, app):print(f"{Colors.CYAN}Objective: {objective}{Colors.RESET}")print(f"{Colors.CYAN}Searching website: {url}{Colors.RESET}")map_search_parameter = query_openai(f"Provide 1-2 search keywords for: {objective}")map_website = app.map_url(url, params={"search": map_search_parameter})links = map_website.get('urls', []) or map_website.get('links', [])rank_prompt = f"""Rank these URLs for relevance to '{objective}'. Respond only with JSON:{json.dumps(links, indent=2)}"""ranked_json = query_openai(rank_prompt)ranked_results =extract_json_from_response(ranked_json)return [result["url"] for result in ranked_results[:3]]def main():url = input(f"{Colors.BLUE}Enter the website: {Colors.RESET}")objective = input(f"{Colors.BLUE}Enter your objective: {Colors.RESET}")links = find_relevant_page_via_map(objective, url, app)if links:print(f"{Colors.GREEN}Relevant links found:{Colors.RESET}")for link in links:print(link)else:print(f"{Colors.RED}No relevant links found.{Colors.RESET}")if __name__ == "__main__":main()

4.你以为这就完了吗,不,上面的内容没有一点挑战性,有挑战的是我们本地部署源代码,来替代调用爬虫官网获取的api的作用(https://github.com/mendableai/firecrawl.git) 

1)安装node。20.17.0版本

我是用nvm直接安装的

nvm install 20.17.0

nvm use 20.17.0

2)安装pnpm。9.12.2

npm install -g pnpm@9.12.2

3)安装redis

sudo apt-get install lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis
sudo systemctl enable redis-server
sudo systemctl start redis-server

4)配置.env

cd /apps/api/ 
vim .env我的.env内容如下:
# ===== Required ENVS =====
NUM_WORKERS_PER_QUEUE=8
PORT=3002
HOST=0.0.0.0
REDIS_URL=redis://localhost:6379
REDIS_RATE_LIMIT_URL=redis://localhost:6379USE_DB_AUTHENTICATION=false# ===== Optional ENVS =====# Supabase 不使用,留空即可
SUPABASE_ANON_TOKEN=
SUPABASE_URL=
SUPABASE_SERVICE_TOKEN=# 其他可选,根据你是否用到再填
TEST_API_KEY=
SCRAPING_BEE_API_KEY=
OPENAI_API_KEY=
BULL_AUTH_KEY=
PLAYWRIGHT_MICROSERVICE_URL=
LLAMAPARSE_API_KEY=
SLACK_WEBHOOK_URL=
POSTHOG_API_KEY=
POSTHOG_HOST=

4)安装依赖项

# cd apps/api # to make sure you're in the right folder
pnpm install # make sure you have pnpm version 9+!

 5)启动服务,第一个服务

redis,刚才已经启动过了

第二个服务:

cd apps/api/ 目录并运行
pnpm run workers

第三个服务

导航到 apps/api/ 目录并运行
pnpm run start

6)测试

curl -X GET http://localhost:3002/test

会出现hello world

7)测试抓取端点

curl -X POST http://localhost:3002/v1/crawl \-H 'Content-Type: application/json' \-d '{"url": "https://mendable.ai"}'

返回

8)加入ai功能实现官网的能力

第一步,我们先抓取

curl -X POST http://localhost:3002/v1/crawl     -H 'Content-Type: application/json'     -d '{
      "url": "https://docs.cline.bot/"
    }'

然后得到结果,将结果保存到txt中

curl http://localhost:3002/v1/crawl/d40ed298-c2e5-4c0a-99f8-19f17f3f3f7c > out.txt

然后将其中的markdown信息保存起来

用下面的脚本

import json# ===== 配置 =====
INPUT_JSON_FILE = "out.txt"       # 你的 firecrawl 返回的 json 文件
OUTPUT_MARKDOWN_FILE = "cline_docs.md"  # 输出的 markdown 文件# ===== 主程序 =====
def extract_and_save():with open(INPUT_JSON_FILE, "r", encoding="utf-8") as f:data = json.load(f)if not data.get("success"):print("❌ JSON 非正常,可能爬虫失败")returnall_md = ""# 提取所有 data[i]["markdown"]for i, item in enumerate(data.get("data", [])):md = item.get("markdown", "")all_md += f"\n\n---\n\n# Page {i+1}\n\n"  # 每一页加个分隔all_md += md# 保存到 markdown 文件with open(OUTPUT_MARKDOWN_FILE, "w", encoding="utf-8") as f:f.write(all_md)print(f"✅ 成功提取 {len(data.get('data', []))} 个 markdown 页面")print(f"✅ 已保存到 {OUTPUT_MARKDOWN_FILE}")if __name__ == "__main__":extract_and_save()

 得到一个md文件

再然后通过大模型分析md文件

import os
import json
from openai import OpenAI# ==== 配置 ====
client = OpenAI(base_url="https://openrouter.ai/api/v1",api_key="sk-or"
)MD_FILE = "cline_docs.md"
CHUNK_SIZE = 4000   # 按 token 预估, 可调整
OUTPUT_DIR = "outputs"
os.makedirs(OUTPUT_DIR, exist_ok=True)# ==== 工具函数 ====
def split_markdown(md_text, chunk_size=4000):"""将markdown分块"""paragraphs = md_text.split("\n\n")chunks = []current_chunk = ""for p in paragraphs:if len(current_chunk) + len(p) < chunk_size:current_chunk += p + "\n\n"else:chunks.append(current_chunk.strip())current_chunk = p + "\n\n"if current_chunk.strip():chunks.append(current_chunk.strip())return chunks# ==== LLM 处理 ====
def ask_llm(text, index):completion = client.chat.completions.create(extra_headers={"HTTP-Referer": "http://localhost","X-Title": "firecrawl-agent",},model="google/gemini-2.5-pro-exp-03-25:free",messages=[{"role": "user", "content": f"请总结以下文档内容:\n\n{text}"}])result = completion.choices[0].message.content.strip()with open(f"{OUTPUT_DIR}/chunk_{index+1}.txt", "w", encoding="utf-8") as f:f.write(result)print(f"✅ chunk_{index+1} 已完成")# ==== 主流程 ====
if __name__ == "__main__":with open(MD_FILE, "r", encoding="utf-8") as f:markdown = f.read()chunks = split_markdown(markdown, CHUNK_SIZE)print(f"共分成 {len(chunks)} 个 chunk")for i, chunk in enumerate(chunks):ask_llm(chunk, i)print("\n✅ 全部分析完成,已保存到 outputs/ 目录")

最后得到outputs目录(要注意免费api的速率限制)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

洛谷题单3-P5720 【深基4.例4】一尺之棰-python-流程图重构

题目描述 《庄子》中说到&#xff0c;“一尺之棰&#xff0c;日取其半&#xff0c;万世不竭”。第一天有一根长度为 a a a 的木棍&#xff0c;从第二天开始&#xff0c;每天都要将这根木棍锯掉一半&#xff08;每次除 2 2 2&#xff0c;向下取整&#xff09;。第几天的时候木…

c++中的auto关键字

在 C 中&#xff0c;auto 是一个类型推断关键字&#xff08;C11 引入&#xff09;&#xff0c;允许编译器根据变量的初始化表达式自动推导其类型。它极大地简化了代码编写&#xff0c;尤其在涉及复杂类型或模板的场景中。以下是 auto 的详细说明&#xff1a; 1. 基本用法 1.1 …

开发指南111-关闭所有打开的子窗口

门户系统是通过window.open通过单点登录的模式打开子系统的&#xff0c;这就要求门户系统退出时&#xff0c;关闭所有打开的子系统。 平台处理这一问题的核心原理如下&#xff1a; 主窗口定义&#xff1a; allChildWindows:[], //所有子窗口 pushChildWindow(childWindow){ …

Kotlin语言进阶:协程、Flow、Channel详解(二)

Kotlin语言进阶:协程、Flow、Channel详解(二) 一、Flow基础 1.1 什么是Flow Flow是Kotlin提供的用于处理异步数据流的解决方案,它建立在协程之上,具有以下特点: 冷流特性:只有在收集时才会开始发射数据背压处理:自动处理生产者和消费者速度不匹配的问题组合操作:提…

mysql中my.cnf权限不能过大。否则无法生效

mysql 报错 World-writable config file ‘/etc/my.cnf‘ is ignored. /etc/my.cnf 配置文件, 或着docker 挂载的配置文件(宿主机中的配置文件),权限过大 如是二进制启动 chmod 644 /etc/my.cnf 如是docker启动 chmod 644 /opt/docker-data/mysql/conf/my.cnf 重启服务,就可…

Spring 中的 @Autowired 和 @Resource

&#x1f9e9; 一、Autowired 和 Resource 的基本作用 注解来源作用AutowiredSpring 提供&#xff08;org.springframework.beans.factory.annotation.Autowired&#xff09;按类型 自动注入ResourceJDK 提供&#xff08;javax.annotation.Resource&#xff09;默认按名称 注入…

anomalib—2—输入图像大小调整

三个地方 第一&#xff1a;在定义model时&#xff0c;要在pre_processor里面去定义一个前处理&#xff0c;前处理就一个功能&#xff0c;定义图像的大小 pre_processor0 Patchcore.configure_pre_processor( image_size (128, 128)) model Patchcore( backbone"wide_r…

JSX、支持HTML标签、Ref的使用、虚拟DOM的使用

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

JVM 学习计划表(2025 版)

JVM 学习计划表&#xff08;2025 版&#xff09; &#x1f4da; 基础阶段&#xff08;2 周&#xff09; 1. JVM 核心概念 ​JVM 作用与体系结构 理解 JVM 在 Java 跨平台运行中的核心作用&#xff0c;掌握类加载子系统、运行时数据区、执行引擎的交互流程​内存结构与数据存…

进程内存分布--之理论知识

一个由C/C编译的程序占用的内存分为以下几个部分 &#xff1a; 1、栈区&#xff08;stack&#xff09;&#xff1a;由编译器自动分配释放 &#xff0c;存放函数调用函数的参数值&#xff0c;局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区&#xff08;heap&#xf…

WEB安全--内网渗透--LMNTLM基础

一、前言 LM Hash和NTLM Hash是Windows系统中的两种加密算法&#xff0c;不过LM Hash加密算法存在缺陷&#xff0c;在Windows Vista 和 Windows Server 2008开始&#xff0c;默认情况下只存储NTLM Hash&#xff0c;LM Hash将不再存在。所以我们会着重分析NTLM Hash。 在我们内…

时尚优雅奢华品牌包装徽标设计衬线英文字体安装包 Kagea – Luxury Women Ligature Font

Kagea 是一种复杂的衬线字体&#xff0c;有常规和压缩两种样式&#xff0c;具有 50 连字和替代字体&#xff0c;并支持多种语言。其精致的比例和别致的字体使其成为高端品牌、编辑布局、高档包装、时尚品牌和奢侈品设计的理想选择。 包含内容&#xff1a; TTF、OTF 和 WOFF 格…

cut命令用法

cut 是 Linux/Unix 系统中一个用于按列提取文本内容的命令&#xff0c;常用于处理结构化文本&#xff08;如 CSV、日志、配置文件等&#xff09;。它通过分隔符、字符位置或字节位置来切割文本&#xff0c;提取指定部分。 核心功能 按字段&#xff08;列&#xff09;提取&#…

美国mlb与韩国mlb的关系·棒球9号位

MLB&#xff08;Major League Baseball&#xff0c;美国职业棒球大联盟&#xff09;作为全球最高水平的职业棒球联赛&#xff0c;与韩国市场流行的“MLB”时尚品牌之间存在着授权合作关系&#xff0c;但两者在业务范畴和品牌定位上存在显著差异。 一、品牌授权背景&#xff1a;…

从吉卜力漫画到艺术创造:GPT-4o多种风格绘图Prompt大全

在3月底&#xff0c;GPT-4o掀起了一阵吉卜力绘图浪潮&#xff0c;大家纷纷输入一张图片&#xff0c;让4o模型进行风格化迁移&#xff0c;其中吉卜力风格的漫画在社交媒体上最为火热。在大家争议4o的训练数据是否侵权和4o背后的技术原理的时候&#xff0c;我们先来玩一玩&#x…

Leetcode 3510. Minimum Pair Removal to Sort Array II

Leetcode 3510. Minimum Pair Removal to Sort Array II 1. 解题思路2. 代码实现 题目链接&#xff1a;3510. Minimum Pair Removal to Sort Array II 1. 解题思路 这一题和题目3507. Minimum Pair Removal to Sort Array I本质上是同一道题目&#xff0c;唯一的区别在于时间…

【数学建模】(时间序列模型)ARIMA时间序列模型

ARIMA时间序列模型详解及常见时间序列模型概览 文章目录 ARIMA时间序列模型详解及常见时间序列模型概览1 引言2 ARIMA模型的基本概念3 ARIMA模型的组成部分详解3.1 AR模型 (自回归模型)3.2 MA模型 (移动平均模型)3 I (差分) 4 ARIMA模型的建模步骤5 Python实现ARIMA模型6 常见时…

嵌入式AI开发者职业成长路线图

嵌入式AI开发者职业成长路线图 一、核心技术能力构建 1. 深度学习框架 TensorFlow/TensorFlow Lite&#xff1a;适合部署到嵌入式设备PyTorch&#xff1a;研究和原型开发ONNX&#xff1a;模型转换与部署 2. 模型理解与应用 卷积神经网络(CNN)&#xff1a;图像识别、目标检…

单元测试之mockito

简介 mockito是一款模拟测试框架&#xff0c;用于Java开发中的单元测试。通过mockito&#xff0c;可以创建和配置一个对象&#xff0c;通过它来替换对象的外部依赖。 作用&#xff1a;模拟一个类的外部依赖&#xff0c;保证单元测试的独立性。例如&#xff0c;在类A中会调用类…

Oracle数据库数据编程SQL<5 正则表达式函数*****>

Oracle 提供了一组强大的正则表达式函数,用于在 SQL 和 PL/SQL 中进行复杂的模式匹配和文本处理。这些函数基于 POSIX 标准正则表达式,功能强大且灵活。 目录 一、Oracle 正则表达式函数概览 二、函数详解及示例 1. REGEXP_LIKE 2. REGEXP_INSTR 3. REGEXP_SUBSTR 4. …