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)