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.pswp.cn/bicheng/75876.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75876.shtml
英文地址,請注明出處:http://en.pswp.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. …