Crawl4AI进行异步爬虫并提取链接
本文介绍了一个基于Python的异步网页爬虫项目,用于抓取特定网页内容并提取指定年份的年度报告PDF链接。项目采用asyncio、crawl4ai、OpenAI等技术实现高效爬取和智能分析功能,主要包含三个核心模块:通过AsyncWebCrawler异步爬取网页内容;利用OpenAI模型从Markdown中精确提取符合年份要求的PDF链接;使用aiohttp并发下载文件。系统支持命令行参数指定目标
项目概述
该项目是一个异步网页爬虫,旨在从给定的URL中抓取网页内容,并利用OpenAI模型从抓取到的Markdown内容中提取特定年份的年度报告PDF链接,然后下载这些PDF文件。
技术栈
-
Python: 主要开发语言。
-
asyncio: 用于异步操作,提高爬取和下载效率。
-
crawl4ai: 用于网页内容爬取。
-
openai: 用于与OpenAI API交互,进行内容分析和PDF链接提取。
-
aiohttp: 用于异步HTTP请求,实现PDF文件的下载。
-
aiofiles: 用于异步文件操作,提高文件写入效率。
-
dotenv: 用于加载环境变量。
-
logger: 用于日志记录。
核心功能
1. 网页爬取 (main 函数)
-
使用
crawl4ai库的AsyncWebCrawler进行异步网页爬取。 -
配置浏览器为无头模式 (
headless=True)。 -
支持批量URL爬取 (
arun_many)。 -
成功爬取后,对每个网页内容进行后续处理。
2. PDF链接提取 (extract_pdfs_url 函数)
-
利用OpenAI模型: 将网页的Markdown内容作为输入,调用OpenAI的聊天完成API。
-
详细的提示词工程: 提示词(
prompt)定义了严格的规则来识别和提取年度报告PDF链接,包括:-
核心筛选标准: 仅提取明确标识的PDF链接,且文件扩展名必须是
.pdf。 -
年份精准匹配: 必须包含目标年份(通过命令行参数
sys.argv[1]传入,例如2024)的标识,支持数字、中文和英文格式。 -
链接处理: 保留原始URL格式,仅返回纯URL,多个有效链接用英文逗号分隔,无匹配时返回空字符串。
-
-
错误处理: 捕获OpenAI API调用过程中可能发生的异常。
3. PDF文件下载 (download_pdf 和 download_url 函数)
-
download_url:-
异步下载单个URL指向的文件。
-
设置
User-Agent请求头以模拟浏览器访问。 -
设置30秒的下载超时。
-
检查HTTP响应状态码,非200则记录错误。
-
从URL中提取文件名,并构建本地保存路径。
-
使用
aiofiles异步写入文件内容。 -
记录下载成功或失败的信息。
-
-
download_pdf:-
接收从
extract_pdfs_url获取的PDF链接列表和原始网页的base_url。 -
从
base_url中解析出域名,并以此域名创建本地存储文件夹(例如D:/Work/craw4ai_project/data/new/{domain})。 -
使用
asyncio.gather并发执行所有PDF下载任务,提高下载效率。
-
运行流程
-
加载环境变量: 从
.env文件中加载OPENAI_API_KEY,OPENAI_BASE_URL,OPENAI_MODEL等配置。 -
定义目标URL:
urls列表中包含待爬取的网页URL。 -
执行主函数:
main函数启动爬取流程。 -
爬取网页:
AsyncWebCrawler访问每个URL并获取其Markdown内容。 -
提取PDF链接: 对于每个爬取成功的网页,调用
extract_pdfs_url,将Markdown内容和目标年份(通过命令行参数传入)发送给OpenAI模型,获取符合条件的PDF链接。 -
下载PDF文件: 获取到PDF链接后,调用
download_pdf函数,并发下载所有提取到的PDF文件到本地指定目录。
如何运行
-
配置环境变量: 在项目根目录下创建
.env文件,并添加以下内容:OPENAI_API_KEY=你的OpenAI API Key OPENAI_BASE_URL=你的OpenAI API Base URL (例如:https://api.openai.com/v1) OPENAI_MODEL=你使用的OpenAI模型名称 (例如:gpt-4o)
-
安装依赖:
pip install -r requirements.txt # 假设 requirements.txt 包含: # crawl4ai # openai # python-dotenv # aiohttp # aiofiles
-
运行脚本:
python your_script_name.py 2024
其中
your_script_name.py是你的Python文件名,2024是你希望提取的pdf文件年份。
注意事项
-
确保
urls列表中的URL是有效的。 -
OpenAI API的调用会产生费用,请注意使用量。
-
提示词的质量直接影响PDF链接提取的准确性,如有需要可根据实际情况调整提示词内容。
-
下载路径
D:/Work/craw4ai_project/data/new/是硬编码的,建议根据实际需求修改为可配置的路径。 -
命令行参数
sys.argv[1]用于指定目标年份,确保在运行脚本时提供该参数。
代码模块示例
为了更好地理解项目功能,以下是部分核心代码模块的示例:
main 函数 (网页爬取入口)
async def main():
browser_config = BrowserConfig(
headless = True
)
crawler_config = CrawlerRunConfig(
cache_mode = CacheMode.BYPASS
)
async with AsyncWebCrawler(config = browser_config) as crawler:
result = await crawler.arun_many(
urls = urls,
bypass_cache = True,
config = crawler_config
)
for res in result:
if res.success:
logger.debug(f"成功爬取:{res.url}")
pdfs_url = await extract_pdfs_url(res.markdown)
logger.debug(res.markdown)
await download_pdf(pdfs_url,res.url)
else:
logger.debug(res.url)
print("内容下载完成")
extract_pdfs_url 函数 (PDF链接提取)
async def extract_pdfs_url(markdown):
client = OpenAI(
api_key = os.getenv("OPENAI_API_KEY"),
base_url = os.getenv("OPENAI_BASE_URL")
)
model = os.getenv("OPENAI_MODEL")
prompt = f"""
你是一个专业的网页内容分析助手。你的任务是从给定的网页Markdown内容中精准提取目标年份的年度报告PDF链接,请严格遵循以下规则:
...
"""
user_prompt = f"""目标年份:{sys.argv[1]},markdown内容:{markdown}"""
messages = [
{"role":"system","content":prompt},
{"role":"user","content":user_prompt}
]
try:
response = client.chat.completions.create(
model=model,
messages=messages,
stream=False,
temperature=0.7
)
response_content = response.choices[0].message.content
logger.debug(f"大模型处理结果:{response_content}")
pdfs = response_content.split(",")
logger.debug(pdfs)
return pdfs
except Exception as e:
logger.error(f"大模型分析失败: {e}")
download_url 函数 (单个文件下载)
async def download_url(url,folder):
headers = {'User-Agent':'xxxxxxxx'} #替换为自己的用户代理
try:
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers, timeout=30) as response:
if response.status != 200:
logger.error(f"下载失败:{url},-状态码:{response.status}")
filename = url.split('/')[-1]
filepath = os.path.join(folder,filename)
content = await response.read()
async with aiofiles.open(filepath,"ab") as f:
await f.write(content)
logger.debug("下载成功:{filename}")
except Exception as e:
logger.error(f"下载出错:{e}")
download_pdf 函数 (并发PDF下载)
async def download_pdf(pdfs,base_url):
domain = urlparse(base_url).netloc.replace("www.", "")
folder_name = f"D:/Work/craw4ai_project/data/new/{domain}"
os.makedirs(folder_name, exist_ok=True)
download_tasks = [download_url(url,folder_name) for url in pdfs]
await asyncio.gather(*download_tasks)更多推荐

所有评论(0)