首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python 异步爬虫(aiohttp)高效抓取新闻数据

Python 异步爬虫(aiohttp)高效抓取新闻数据

原创
作者头像
小白学大数据
发布2025-07-03 16:40:43
发布2025-07-03 16:40:43
2170
举报

一、异步爬虫的优势 在传统的同步爬虫中,爬虫在发送请求后会阻塞等待服务器响应,直到收到响应后才会继续执行后续操作。这种模式在面对大量请求时,会导致大量的时间浪费在等待响应上,爬取效率较低。而异步爬虫则等待可以在服务器响应的同时,继续执行其他任务,大大提高了爬取效率。 aiohttp 是一个支持异步请求的 Python 库,它基于 asyncio 框架,可以实现高效的异步网络请求。使用 aiohttp 构建异步爬虫,可以在短时间内发起大量请求,同时处理多个响应,从而实现高效的数据抓取。

二、环境准备 在开始编写异步爬虫之前,需要确保已经安装了 Python 以及 aiohttp 库。如果尚未安装 aiohttp 此外,为了更好地处理 HTML 内容,我们还需要安装 beautifulsoup4 库,用于解析 HTML 文档:

三、构建异步爬虫

1. 初始化异步爬虫 首先,我们需要创建一个异步函数来初始化爬虫。在这个函数中,我们将设置异步会话(aiohttp.ClientSession),用于发送网络请求。

代码语言:txt
复制
import aiohttp
import asyncio
from bs4 import BeautifulSoup

async def fetch(session, url):
    """
    异步发送 GET 请求
    :param session: aiohttp.ClientSession 对象
    :param url: 请求的 URL
    :return: 响应的 HTML 内容
    """
    async with session.get(url) as response:
        return await response.text()

2. 解析新闻数据 在获取到新闻页面的 HTML 内容后,我们需要使用 BeautifulSoup 对其进行解析,提取出新闻的标题、链接等关键信息。

代码语言:txt
复制
def parse_news):
(html    """
    解析 HTML 内容,提取新闻信息
    :param html: 新闻页面的 HTML 内容
    :return: 新闻信息列表
    """
    soup = BeautifulSoup(html, 'html.parser')
    news_list = []
    # 假设新闻标题在 <h2> 标签中,新闻链接在 <a> 标签的 href 属性中
    for item in soup.find_all('h2'):
        title = item.get_text()
        link = item.find('a')['href']
        news_list.append({'title': title, 'link': link})
    return news_list

3. 异步任务调度 为了实现高效的异步爬取,我们需要将多个请求任务调度到事件循环中。通过创建多个异步任务,并将它们添加到事件循环中,可以同时发起多个请求。

代码语言:txt
复制
async def main():
    url = 'https://example.com/news'  # 新闻网站的 URL
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, url)
        news_list = parse_news(html)
        for news in news_list:
            print(news)

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

4. 多任务并发 在实际应用中,我们通常需要爬取多个新闻页面。为了提高效率,可以使用 asyncio.gather 方法并发执行多个异步任务。

代码语言:txt
复制

async def fetch_news(session, url):
    html = await fetch(session, url)
    return parse_news(html)

async def main():
    urls = [
        'https://example.com/news/page1',
        'https://example.com/news/page2',
        'https://example.com/news/page3',
        # 更多新闻页面的 URL
    ]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_news(session, url) for url in urls]
        all_news = await asyncio.gather(*tasks)
        for news_list in all_news:
            for news in news_list:
                print(news)

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

四、优化与注意事项

1. 错误处理 在爬取过程中,可能会遇到各种错误,如网络请求超时、服务器返回错误状态码等。为了保证爬虫的稳定性,需要对这些错误进行处理。

代码语言:txt
复制
async def fetch(session, url):
    try:
        async with session.get(url, timeout=10) as response:  # 设置请求超时时间
            response.raise_for_status()  # 检查响应状态码
            return await response.text()
    except asyncio.TimeoutError:
        print(f"请求超时:{url}")
    except aiohttp.ClientResponseError as e:
        print(f"请求错误:{url}, 状态码:{e.status}")
    except Exception as e:
        print(f"未知错误:{url}, 错误信息:{e}")

2. 遵守网站规则 在爬取新闻数据时,需要遵守目标网站的 robots.txt 文件规定,避免对网站造成过大压力。同时,合理设置请求间隔,避免被网站封禁。

3. 数据存储 爬取到的新闻数据可以存储到本地文件、数据库或云存储中,以便后续进行分析和处理。

五、总结 本文介绍了如何使用 Python 的 aiohttp 库构建异步爬虫,高效抓取新闻数据。通过异步请求和并发任务调度,可以显著提高爬取效率。在实际应用中,还需要注意错误处理、遵守网站规则以及数据存储等问题。希望本文能够帮助读者更好地理解和应用 Python 异步爬虫技术。

六、完整代码

代码语言:txt
复制
import aiohttp
import asyncio
from bs4 import BeautifulSoup
# 代理配置
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"
proxyUrl = f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
async def fetch(session, url):
 try:
 async with session.get(url, timeout=10, proxy=proxyUrl) as response:
 response.raise_for_status()
 return await response.text()
 except asyncio.TimeoutError:
 print(f"请求超时:{url}")
 except aiohttp.ClientResponseError as e:
 print(f"请求错误:{url}, 状态码:{e.status}")
 except Exception as e:
 print(f"未知错误:{url}, 错误信息:{e}")
def parse_news(html):
 soup = BeautifulSoup(html, 'html.parser')
 news_list = []
 for item in soup.find_all('h2'):
 title = item.get_text()
 link = item.find('a')['href'] if item.find('a') else None
 if title and link:
 news_list.append({'title': title, 'link': link})
 return news_list
async def fetch_news(session, url):
 html = await fetch(session, url)
 if html:
 return parse_news(html)
 return []
async def main():
 urls = [
 'https://example.com/news/page1',
 'https://example.com/news/page2',
 'https://example.com/news/page3',
 # 更多新闻页面的 URL
 ]
 # 配置代理认证
 proxy_auth = aiohttp.BasicAuth(proxyUser, proxyPass)
 conn = aiohttp.TCPConnector(limit=10) # 限制连接数
 async with aiohttp.ClientSession(connector=conn) as session:
 tasks = [fetch_news(session, url) for url in urls]
 all_news = await asyncio.gather(*tasks)
 for news_list in all_news:
 for news in news_list:
 print(news)
if __name__ == '__main__':
 asyncio.run(main())

若有收获,就点个赞吧

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档