Python自制爬虫框架如何整合多家IT博客平台的文章?

这样就能更方便地寻找技术干货了

Demo 地址: https://techattic.herokuapp.com

自制的爬虫框架介绍: https://zhuanlan.zhihu.com/p/34917713

整理好的 Python 总结: https://github.com/alphardex/python-recipe


Python自制爬虫框架如何整合多家IT博客平台的文章?

3 回复

要整合多家IT博客平台的文章,你需要设计一个可扩展的爬虫框架。核心思路是抽象出通用的爬取流程,然后为每个平台实现具体的解析器。

下面是一个基础框架示例:

import requests
from abc import ABC, abstractmethod
from typing import List, Dict
import json

class Article:
    """文章数据模型"""
    def __init__(self, title: str, content: str, author: str, url: str):
        self.title = title
        self.content = content
        self.author = author
        self.url = url
    
    def to_dict(self):
        return {
            'title': self.title,
            'content': self.content,
            'author': self.author,
            'url': self.url
        }

class BaseCrawler(ABC):
    """爬虫基类"""
    
    def __init__(self, base_url: str):
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })
    
    @abstractmethod
    def parse_article_list(self, html: str) -> List[str]:
        """解析文章列表页,返回文章详情页链接"""
        pass
    
    @abstractmethod
    def parse_article_detail(self, html: str) -> Article:
        """解析文章详情页,返回Article对象"""
        pass
    
    def fetch(self, url: str) -> str:
        """发送HTTP请求"""
        response = self.session.get(url, timeout=10)
        response.raise_for_status()
        return response.text
    
    def crawl(self, start_url: str) -> List[Article]:
        """执行爬取流程"""
        articles = []
        
        # 获取列表页
        list_html = self.fetch(start_url)
        article_urls = self.parse_article_list(list_html)
        
        # 遍历每篇文章
        for url in article_urls:
            try:
                detail_html = self.fetch(url)
                article = self.parse_article_detail(detail_html)
                articles.append(article)
            except Exception as e:
                print(f"爬取 {url} 失败: {e}")
        
        return articles

# 具体平台实现示例
class CSDNCrawler(BaseCrawler):
    """CSDN爬虫"""
    
    def parse_article_list(self, html: str) -> List[str]:
        # 这里简化处理,实际需要解析HTML
        # 可以使用BeautifulSoup或lxml
        import re
        return re.findall(r'https://blog.csdn.net/\w+/article/details/\d+', html)
    
    def parse_article_detail(self, html: str) -> Article:
        # 解析CSDN文章页面的具体逻辑
        # 这里返回示例数据
        return Article(
            title="示例标题",
            content="示例内容",
            author="示例作者",
            url="https://example.com"
        )

class JuejinCrawler(BaseCrawler):
    """掘金爬虫"""
    
    def parse_article_list(self, html: str) -> List[str]:
        # 解析掘金文章列表
        import re
        return re.findall(r'https://juejin.cn/post/\d+', html)
    
    def parse_article_detail(self, html: str) -> Article:
        # 解析掘金文章详情
        return Article(
            title="掘金文章",
            content="掘金内容",
            author="掘金作者",
            url="https://juejin.cn"
        )

class CrawlerManager:
    """爬虫管理器"""
    
    def __init__(self):
        self.crawlers = {}
    
    def register_crawler(self, name: str, crawler: BaseCrawler):
        self.crawlers[name] = crawler
    
    def run_all(self, config: Dict[str, str]) -> Dict[str, List[Article]]:
        """运行所有爬虫"""
        results = {}
        
        for name, start_url in config.items():
            if name in self.crawlers:
                print(f"开始爬取 {name}...")
                articles = self.crawlers[name].crawl(start_url)
                results[name] = articles
                print(f"{name} 爬取完成,获取 {len(articles)} 篇文章")
        
        return results
    
    def save_results(self, results: Dict[str, List[Article]], filename: str):
        """保存结果到JSON文件"""
        data = {}
        for platform, articles in results.items():
            data[platform] = [article.to_dict() for article in articles]
        
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

# 使用示例
if __name__ == "__main__":
    manager = CrawlerManager()
    
    # 注册爬虫
    manager.register_crawler("csdn", CSDNCrawler("https://blog.csdn.net"))
    manager.register_crawler("juejin", JuejinCrawler("https://juejin.cn"))
    
    # 配置各平台的起始URL
    config = {
        "csdn": "https://blog.csdn.net/nav/python",
        "juejin": "https://juejin.cn/frontend"
    }
    
    # 执行爬取
    results = manager.run_all(config)
    
    # 保存结果
    manager.save_results(results, "articles.json")

这个框架的关键点:

  1. 抽象基类BaseCrawler定义了爬虫的标准接口,所有平台爬虫都要继承并实现parse_article_listparse_article_detail方法。

  2. 数据模型Article类统一了文章的数据结构,确保不同平台的数据格式一致。

  3. 管理器模式CrawlerManager负责注册和调度各个爬虫,方便扩展新平台。

  4. 扩展性:要新增平台,只需创建一个新的爬虫类继承BaseCrawler,然后在管理器中注册即可。

实际使用时需要注意:

  • 需要根据各平台的实际HTML结构实现具体的解析逻辑
  • 建议使用BeautifulSouplxml进行HTML解析
  • 添加适当的延迟和错误处理避免被封IP
  • 遵守各平台的robots.txt协议

总结建议:用抽象基类定义接口,为每个平台实现具体解析器。


hello, 欢迎使用 crawlab 来集成 looter,https://www.github.com/tikazyq/crawlab

没人做网站爬虫规则共享平台吗?爬虫框架太多

回到顶部