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

Python异步循环嵌套实现及高效网页爬虫开发技术问询

解决Python异步循环嵌套的网页爬虫实现方案

Alright, let's figure out how to implement async nested loops for your high-performance web scraping bot. Since you need fast, concurrent data retrieval, Python's asyncio paired with aiohttp (for async HTTP requests) is perfect here. Let's break this down step by step:

1. 完善Query类的异步支持

首先,我们需要给你的Query类添加异步方法来处理HTTP请求和页面解析,同时补全你未完成的visible方法(用于过滤不可见文本):

import asyncio
import aiohttp
import re
from bs4 import BeautifulSoup  # 需提前安装:pip install beautifulsoup4

class Query:
    # 每个查询包含搜索词及需检查共性的内容
    def __init__(self, query, terms):
        assert type(query) == str
        self.query = query
        self.terms = terms  # 存储需要检查的共性关键词列表
        self.response = None  # 存储返回的HTML内容
        self.matching_terms = []  # 存储匹配到的共性内容

    def visible(self, element):
        """判断元素文本是否可见,过滤掉样式、脚本、注释等无关内容"""
        if element.parent.name in ['style', 'script', '[document]', 'head', 'title']:
            return False
        elif re.match('<!--.*-->', str(element)):  # 过滤HTML注释
            return False
        return True

    async def fetch_and_parse(self, session):
        """异步执行请求、解析页面,并检查terms共性内容"""
        # 替换成你实际的目标URL模板(比如搜索API或目标站点的搜索地址)
        target_url = f"https://example.com/search?q={self.query}"
        
        try:
            # 复用session发起异步请求
            async with session.get(target_url) as resp:
                if resp.status != 200:
                    print(f"⚠️ 请求失败 {target_url},状态码: {resp.status}")
                    return
                
                # 异步读取响应文本
                self.response = await resp.text()
                
                # 解析页面,提取可见文本
                soup = BeautifulSoup(self.response, 'html.parser')
                visible_texts = filter(self.visible, soup.find_all(text=True))
                clean_page_text = ' '.join([text.strip() for text in visible_texts if text.strip()])
                
                # 嵌套循环:检查每个term是否存在于页面文本中
                for term in self.terms:
                    if term.lower() in clean_page_text.lower():
                        self.matching_terms.append(term)
                        print(f"✅ 查询 '{self.query}' 匹配到关键词: {term}")
                        
        except Exception as e:
            print(f"❌ 处理查询 '{self.query}' 时出错: {str(e)}")

2. 主类Whole的异步调度逻辑

接下来,主类Whole需要生成Query对象,并通过异步循环并发执行所有爬虫任务:

class Whole:
    def __init__(self, queries_config):
        # queries_config是列表,每个元素为(搜索词, 需检查的关键词列表)
        self.queries = [Query(query_str, terms_list) for query_str, terms_list in queries_config]

    async def run_scraper(self):
        """启动异步爬虫任务,并发处理所有Query"""
        # 创建aiohttp会话,复用连接池提升性能
        async with aiohttp.ClientSession() as session:
            # 异步并发执行所有Query的fetch_and_parse任务
            await asyncio.gather(
                *[query.fetch_and_parse(session) for query in self.queries]
            )
        
        # 所有任务完成后,输出汇总结果
        print("\n📊 爬虫任务完成!结果汇总:")
        for query in self.queries:
            print(f"查询: '{query.query}' | 匹配到的关键词: {query.matching_terms}")

3. 运行爬虫示例

最后,编写入口代码启动整个爬虫:

if __name__ == "__main__":
    # 示例配置:替换成你实际的查询和关键词
    queries_config = [
        ("python异步爬虫", ["asyncio", "aiohttp", "并发"]),
        ("BeautifulSoup教程", ["HTML解析", "网页抓取", "数据提取"])
    ]

    # 初始化并启动爬虫
    scraper = Whole(queries_config)
    asyncio.run(scraper.run_scraper())

关键注意点

  • 异步并发核心:asyncio.gather实现了外层的异步循环,让所有Query任务同时执行,避免了同步爬虫的串行等待
  • 嵌套循环处理:每个Query内部的terms检查是同步循环(因为是CPU绑定的文本匹配,速度很快);如果你的terms检查涉及额外IO操作(比如每个term要请求其他URL),可以把这部分也改成异步循环,用asyncio.gather处理每个term的任务
  • 性能优化:复用aiohttp.ClientSession可以保持TCP连接池,减少握手开销,大幅提升爬虫速度
  • 容错性:添加异常处理确保单个Query的失败不会影响其他任务的执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:12:06