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

如何构建可无限运行的网页爬虫?性能优化与技术选型咨询

无限运行网页爬虫实现方案(解决速度慢、中途停止问题)

核心逻辑修正

你原来的while(num_links_in_page > 0)逻辑有漏洞——当前页面无链接不代表整个爬取任务结束,应该维护一个待爬URL队列,只要队列不为空就持续运行。修正后的核心逻辑伪代码:

初始化待爬队列(放入起始URL)
初始化已爬URL集合(去重用)

while 队列不为空:
    取出一个URL
    如果URL已爬过,跳过
    标记为已爬
    请求页面获取HTML
    解析HTML提取title、meta、文章内容
    将数据存入MySQL
    提取页面内的有效链接(过滤目标域名、排除已爬URL)
    将新链接加入队列

语言选型与实现建议

1. Python(优先推荐)

Python的爬虫生态成熟,异步库能大幅提升爬取速度,且学习成本低。用aiohttp做异步请求,BeautifulSoup解析HTML,示例代码:

import asyncio
from aiohttp import ClientSession
from bs4 import BeautifulSoup
import pymysql

# 数据库连接(按需配置)
db_conn = pymysql.connect(host='localhost', user='root', password='your_pwd', db='spider_db')
cursor = db_conn.cursor()

visited_urls = set()
queue = asyncio.Queue()

# 解析HTML函数
def parse_html(html, url):
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.title.string if soup.title else ''
    # 提取meta标签(以description为例)
    meta_desc = soup.find('meta', attrs={'name': 'description'})
    meta_content = meta_desc['content'] if meta_desc else ''
    # 提取所有p标签内容
    p_content = '\n'.join([p.get_text(strip=True) for p in soup.find_all('p')])
    return title, meta_content, p_content, url

# 批量插入数据库(优化写入速度)
def batch_insert(data_list):
    sql = """INSERT INTO spider_data(html, title, meta, content, url)
             VALUES(%s, %s, %s, %s, %s)
             ON DUPLICATE KEY UPDATE html=VALUES(html)"""
    try:
        cursor.executemany(sql, data_list)
        db_conn.commit()
    except Exception as e:
        print(f"DB insert error: {str(e)}")
        db_conn.rollback()

async def crawl(url, session, batch_data):
    if url in visited_urls:
        return
    visited_urls.add(url)
    try:
        # 模拟浏览器请求头,避免被拦截
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
        }
        async with session.get(url, timeout=12, headers=headers) as resp:
            if resp.status not in [200, 201]:
                print(f"Skip {url} - Status: {resp.status}")
                return
            html = await resp.text()
            title, meta, content, url = parse_html(html, url)
            batch_data.append((html, title, meta, content, url))
            
            # 提取页面内的目标域名链接(这里假设目标域名为example.com,按需修改)
            soup = BeautifulSoup(html, 'html.parser')
            for a_tag in soup.find_all('a', href=True):
                link = a_tag['href']
                # 处理相对链接
                if link.startswith('/'):
                    link = f"https://example.com{link}"
                # 只保留目标域名的链接
                if 'example.com' in link and link not in visited_urls:
                    await queue.put(link)
                    
    except Exception as e:
        print(f"Error crawling {url}: {str(e)}")

async def main(initial_url):
    await queue.put(initial_url)
    batch_data = []
    batch_size = 10  # 每10条数据批量插入一次
    async with ClientSession() as session:
        while not queue.empty():
            url = await queue.get()
            await crawl(url, session, batch_data)
            # 达到批量大小就插入数据库
            if len(batch_data) >= batch_size:
                batch_insert(batch_data)
                batch_data = []
            queue.task_done()
        # 插入剩余数据
        if batch_data:
            batch_insert(batch_data)
    # 关闭数据库连接
    cursor.close()
    db_conn.close()

if __name__ == "__main__":
    asyncio.run(main("https://example.com"))

2. PHP/JavaScript方案(不换语言的选择)

  • PHP:用GuzzleHttp的异步请求实现并发,配合DOMDocument解析HTML,用Redis或者MySQL存储待爬队列和已爬URL,避免重复请求。
  • JavaScript(Node.js):用axios配合Promise.all控制并发数,用cheerio解析HTML,同样需要维护去重集合和持久化队列。

速度提升关键措施

  • 异步/并发请求:不要串行爬取,控制并发数(建议5-10,根据目标网站抗压能力调整),避免单线程阻塞。
  • 链接去重:用内存集合(如Python的set)+ 数据库唯一索引双重去重,避免重复请求浪费资源。
  • 请求优化:设置合理超时时间(10-15秒),只请求HTML文本(禁止下载图片、视频等静态资源),模拟浏览器请求头。
  • 批量写入数据库:不要爬一条插一条,积累一定数量后批量插入,减少数据库IO开销。

解决中途停止问题

  • 全局异常捕获:对每个请求、解析、数据库操作加异常捕获,记录错误日志后继续执行,避免单个请求崩溃导致整个爬虫停止。
  • 队列持久化:把待爬URL存入MySQL或者本地文件,爬虫重启后可以从上次的队列继续爬取,不会前功尽弃。
  • 基础反反爬:设置随机请求间隔(1-3秒),轮换User-Agent,避免被目标网站识别为爬虫封禁。

MySQL表结构参考

CREATE TABLE spider_data (
    id INT AUTO_INCREMENT PRIMARY KEY,
    url VARCHAR(255) UNIQUE NOT NULL,  -- 唯一索引去重
    html LONGTEXT,
    title VARCHAR(255),
    meta TEXT,
    content TEXT,
    crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 12:40:50