You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现新闻网站全异步爬取?列表页与文章爬取并发方案

异步新闻爬虫优化实现

核心问题分析

当前代码中的get_urls是阻塞调用,导致列表页请求必须等待当前页所有文章爬取完成后才能执行,无法发挥异步IO的并发优势。需要将get_urls改造为异步函数,并调整任务调度逻辑,让下一页列表请求与当前页文章爬取并行执行。

步骤1:将get_urls改造为异步函数

使用aiohttp发送异步GET请求,解析HTML获取新闻链接和下一页URL(示例基于BeautifulSoup,可根据实际网站结构调整解析逻辑):

import asyncio
import aiohttp
from bs4 import BeautifulSoup

TAG_URL = "https://example.com/news/category/{}"  # 替换为目标网站的分类URL模板

async def get_urls(session: aiohttp.ClientSession, url: str) -> tuple[list[str], str | None]:
    """异步获取新闻链接和下一页URL"""
    async with session.get(url) as resp:
        if not resp.ok:
            resp.raise_for_status()
        html = await resp.text()
    
    soup = BeautifulSoup(html, "html.parser")
    # 解析新闻详情页链接(替换为目标网站的CSS选择器)
    news_urls = [a["href"] for a in soup.select("div.news-item a.title")]
    # 解析下一页URL(替换为目标网站的下一页按钮选择器)
    next_page_elem = soup.select_one("a.next-page")
    next_url = next_page_elem["href"] if next_page_elem else None
    
    return news_urls, next_url

步骤2:优化主逻辑实现并发

调整任务调度,让列表页请求与文章爬取任务并行执行,无需等待当前页所有文章爬完再请求下一页:

async def parse_page(session: aiohttp.ClientSession, url: str, semaphore: asyncio.Semaphore):
    """异步爬取单篇新闻详情页(示例逻辑,需根据需求修改)"""
    async with semaphore:
        async with session.get(url) as resp:
            if not resp.ok:
                print(f"Failed to fetch {url}: {resp.status}")
                return
            article_html = await resp.text()
            # 解析文章标题、内容等逻辑...
            print(f"Successfully crawled {url}")

async def main():
    # 限制并发请求数,避免触发反爬
    semaphore = asyncio.Semaphore(15)
    tasks = []
    
    async with aiohttp.ClientSession() as session:
        current_url = TAG_URL.format("economy")
        
        while current_url:
            # 异步获取当前页新闻链接和下一页URL
            news_urls, current_url = await get_urls(session, current_url)
            
            # 为当前页所有新闻创建爬取任务
            for url in news_urls:
                task = asyncio.create_task(parse_page(session, url, semaphore))
                tasks.append(task)
    
    # 等待所有爬取任务完成
    await asyncio.gather(*tasks)

if __name__ == "__main__":
    asyncio.run(main())

关键优化点

  • 全异步IO:所有网络请求均使用aiohttp异步实现,避免阻塞事件循环。
  • 并发调度:获取当前页新闻链接后,立即启动下一页的列表请求,同时当前页的文章爬取任务在后台执行,大幅提升爬取效率。
  • 并发量控制:通过asyncio.Semaphore限制同时发起的请求数,降低被网站封禁的风险。

内容的提问来源于stack exchange,提问作者Deeproad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:30:38