Scrapy利器:构建强大爬虫,轻松获取所需数据!

爬虫开发中,Scrapy绝对是一把利器。它不单单是一个爬虫框架,更像是一个完整的数据采集平台。写过爬虫的同学大概率用过requests+beautifulsoup的组合,但遇到大规模爬取时就会感觉力不从心。这时候就要请出Scrapy这个重量级选手了。

框架核心解析

Scrapy采用组件化设计,各个模块之间配合默契。主要包含这么几个核心组件:

# Spider组件示例

import scrapy

class BookSpider(scrapy.Spider):

    name = 'bookspider'

    start_urls = ['http://books.example.com']

    def parse(self, response):

        for book in response.css('.book-item'):

            yield {

                'title': book.css('.title::text').get(),

                'price': book.css('.price::text').get(),

                'author': book.css('.author::text').get()

            }

⚠️ 小贴士:

  • Spider类必须定义name属性
  • parse方法是处理响应的入口
  • 用yield返回数据比return更省内存

中间件玩法

中间件可以说是Scrapy的一大亮点,能让你在请求前后做各种骚操作:

class CustomMiddleware:

    def process_request(self, request, spider):

        # 随机切换User-Agent

        request.headers['User-Agent'] = get_random_ua()

    def process_response(self, request, response, spider):

        # 检查响应状态

        if response.status != 200:

            logging.warning(f'Bad status: {response.status}')

        return response

项目实战:豆瓣图书爬虫

光说不练假把式,整个实例体会下:

class DoubanSpider(scrapy.Spider):

    name = 'douban'

    custom_settings = {

        'ROBOTSTXT_OBEY': False, # 看心情遵守robots协议

        'CONCURRENT_REQUESTS': 16 # 并发数调高点

    }

    def start_requests(self):

        # 构造初始请求

        base_url = 'https://book.douban.com/tag/编程?start={}&type=T'

        for i in range(0, 200, 20):

            yield scrapy.Request(base_url.format(i))

    def parse(self, response):

        books = response.css('#subject_list .subject-item')

        for book in books:

            yield {

                'title': book.css('h2 a::text').get().strip(),

                'rate': book.css('.rating_nums::text').get(),

                'desc': book.css('.pub::text').get().strip()

            }

⚠️ 小贴士:

  • 记得处理反爬,该上代理上代理
  • 数据清洗很重要,strip()走起来
  • 别把并发调太高,小心被封

调度器优化

默认的调度器用的内存队列,数据量大了会有点吃不消。可以换用Redis来存储请求队列:

# settings.py

SCHEDULER = “scrapy_redis.scheduler.Scheduler”

DUPEFILTER_CLASS = “scrapy_redis.dupefilter.RFPDupeFilter”

REDIS_URL = 'redis://localhost:6379'

⚠️ 小贴士:

  • Redis持久化记得打开
  • 定期清理过期请求
  • 善用布隆过滤器去重

Pipeline数据处理

爬下来的数据总得存起来,Pipeline就是干这个的:

class MongoPipeline:

    def __init__(self):

        self.mongo_uri = 'mongodb://localhost:27017'

        self.mongo_db = 'books'

    def process_item(self, item, spider):

        # 存入MongoDB

        collection = self.mongo_db['douban_books']

        collection.insert_one(dict(item))

        return item

写爬虫最重要的是要有耐心,慢慢摸索目标网站的特点。代码写得再漂亮,爬不到数据也是白搭。

⚠️ 小贴士:

  • 善用延时和随机等待
  • 数据备份很重要
  • 监控爬虫运行状态

数据采集这活儿吧,讲究的是持久战。代码写完只是开始,调试优化才是重点。不过有了Scrapy这神器,爬虫开发效率蹭蹭往上涨,剩下的就是跟反爬斗智斗勇了。

来源:青言悉语

THE END