为了账号安全,请及时绑定邮箱和手机立即绑定

Scrapy项目实战:新手从入门到上手指南

标签:
Python 爬虫
概述

本文详细介绍了如何从零开始搭建Scrapy环境并编写简单的爬虫项目,涵盖了Scrapy的基本架构、组件配置以及实战演练。通过具体示例代码,新手可以快速上手掌握Scrapy项目实战。

Scrapy简介与环境搭建

Scrapy是什么

Scrapy 是一个高度模块化的开源爬虫框架,用于从网站上抓取数据。它被广泛应用于数据提取、网络爬虫、网页自动化等场景。Scrapy设计之初就考虑到了可维护性和扩展性,通过不同的组件如Spider、Item、Pipeline等实现不同的功能,使得开发者能够专注于业务逻辑的实现而无需过多关注底层实现。

Scrapy的基本架构

Scrapy采用异步模型来处理网络请求,其主要组件包括:

  1. Spider:定义爬虫行为(例如请求哪个URL,提取哪些数据)。
  2. Item:定义爬取的数据结构。
  3. Item Pipeline:对爬取的数据进行清洗、验证或存储。
  4. Downloader:负责发起网络请求。
  5. Scheduler:管理待爬取的请求队列。
  6. Downloader Middlewares:在下载器和Spiders之间提供了更多的灵活性。
    7..
  7. Spider Middleware:在Scrapy引擎和Spiders之间提供了更多的灵活性。
  8. Scrapy Shell:交互式命令行环境,方便调试。

开发环境搭建

为了搭建Scrapy开发环境,首先需要安装Python。以下是安装步骤:

  1. 下载Python并安装。推荐使用Python 3.8及以上版本。
  2. 安装Scrapy。在命令行中运行以下命令安装:
    pip install scrapy
  3. 安装虚拟环境工具virtualenvvenv,以避免项目间环境冲突。
    pip install virtualenv
  4. 创建一个虚拟环境并激活。
    virtualenv my_env
    source my_env/bin/activate  # 在Windows上,使用 `my_env\Scripts\activate`

快速上手Scrapy的第一个项目

通过Scrapy shell快速上手,以一个简单的新闻网站爬虫为例。

  1. 创建一个新的Scrapy项目。
    scrapy startproject my_first_project
  2. 导航到新项目目录并创建一个新的Spider。
    cd my_first_project
    scrapy genspider my_first_spider example.com
  3. 编辑生成的Spider文件,定义基础抓取逻辑。

    import scrapy
    
    class MyFirstSpider(scrapy.Spider):
       name = 'my_first_spider'
       allowed_domains = ['example.com']
       start_urls = [
           'http://example.com'
       ]
    
       def parse(self, response):
           for title in response.css('title'):
               yield {'title_text': title.get()}
  4. 运行爬虫。
    scrapy crawl my_first_spider

通过以上步骤,用户可以快速创建并运行一个简单的Scrapy爬虫。

Scrapy的基本组件与配置

Scrapy的项目结构

Scrapy项目的标准目录结构:

my_first_project/
├── my_first_project/
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders/
│       └── my_first_spider.py
├── scrapy.cfg
└── requirements.txt

主要组件介绍

Spider

  • 功能:定义爬虫的行为,如从哪个URL开始抓取,抓取哪些数据。
  • 示例代码

    import scrapy
    
    class MyAnotherSpider(scrapy.Spider):
      name = 'my_another_spider'
      allowed_domains = ['example.org']
      start_urls = ['http://example.org']
    
      def parse(self, response):
          for item in response.css('div.item'):
              yield {
                  'title': item.css('h2 a::text').get(),
                  'link': item.css('h2 a::attr(href)').get(),
                  'desc': item.css('p::text').get()
              }

Item

  • 功能:定义爬取的数据结构。
  • 示例代码
    class MyItem(scrapy.Item):
      title = scrapy.Field()
      link = scrapy.Field()
      desc = scrapy.Field()

Pipeline

  • 功能:对爬取的数据进行处理,如清洗、验证或存储。
  • 示例代码
    class MyPipeline(object):
      def process_item(self, item, spider):
          if not item['title']:
              raise DropItem("Missing title in %s" % item)
          return item

配置文件设置

Scrapy的配置可以通过settings.py文件来控制。例如,开启或关闭日志记录,设置下载延迟等。

  • 示例代码
    FEED_FORMAT = 'jsonlines'
    FEED_URI = 'results.jsonl'
    LOG_LEVEL = 'WARNING'
    DOWNLOAD_DELAY = 0.5
基本的爬虫编写

编写简单的网页爬虫

编写一个简单的爬虫,从一个网页上提取所有链接和标题。

  • 示例代码

    import scrapy
    
    class SimpleSpider(scrapy.Spider):
      name = 'simple_spider'
      allowed_domains = ['example.net']
      start_urls = ['http://example.net']
    
      def parse(self, response):
          for link in response.css('a'):
              yield {
                  'href': link.attrib['href'],
                  'text': link.attrib['text']
              }

使用XPath和CSS选择器

XPath 和 CSS 选择器是Scrapy中两种常用的语法,用于从HTML中提取数据。

  • 示例XPath
    response.xpath('//div[@class="item"]/h2/a/text()').get()
  • 示例CSS
    response.css('div.item h2 a::text').get()

捕捉和处理异常

处理爬虫过程中出现的异常。

  • 示例代码

    import scrapy
    
    class ExceptionSpider(scrapy.Spider):
      name = 'exception_spider'
      allowed_domains = ['example.com']
      start_urls = ['http://example.com']
    
      def parse(self, response):
          try:
              yield {
                  'data': response.css('div.missing').get()
              }
          except Exception as e:
              print(f'出现异常:{e}')
              pass

数据存储与处理

数据存储方式

Scrapy支持多种数据存储方式,如CSV、JSON、数据库等。

  • 示例代码(保存为JSON):
    FEED_FORMAT = 'json'
    FEED_URI = 'output.json'

Pipeline的使用

使用Pipeline对爬取的数据进行清洗和格式化。

  • 示例代码
    class MyCustomPipeline(object):
      def process_item(self, item, spider):
          item['title'] = item['title'].strip()
          return item

数据清洗与格式化

清洗数据,去除不必要的字符或格式化数据。

  • 示例代码

    def clean_data(self, text):
      return text.replace('\n', '').strip()
    
    class MySpider(scrapy.Spider):
      def parse(self, response):
          cleaned_text = self.clean_data(response.css('body::text').get())
          yield {'cleaned_text': cleaned_text}
进阶功能与技巧

模拟登录和请求头设置

模拟登录和设置请求头信息。

  • 示例代码

    import scrapy
    
    class LoginSpider(scrapy.Spider):
      name = 'login_spider'
      allowed_domains = ['example.com']
    
      def start_requests(self):
          return [scrapy.FormRequest('http://example.com/login',
                                     formdata={'username': 'test', 'password': 'test'},
                                     callback=self.logged_in)]
    
      def logged_in(self, response):
          if 'Login failed' in response.text:
              self.log("Login failed")
          else:
              yield scrapy.Request('http://example.com/protected',
                                   callback=self.parse_page)
    
      def parse_page(self, response):
          for item in response.css('div.item'):
              yield {
                  'title': item.css('h2 a::text').get(),
                  'link': item.css('h2 a::attr(href)').get(),
                  'desc': item.css('p::text').get()
              }

中间件的使用

中间件允许在请求和响应之间插入额外的处理逻辑。

  • 示例代码
    class MyCustomMiddleware(object):
      def process_request(self, request, spider):
          if not request.meta.get('proxy'):
              request.meta['proxy'] = 'http://proxy.example.com'
          return request

处理动态网页和JavaScript渲染

对于动态网页,使用scrapy-playwright等库来渲染JavaScript。

  • 示例代码

    pip install scrapy-playwright
    import scrapy
    from scrapy_playwright.page import PageMethod
    
    class DynamicSpider(scrapy.Spider):
      name = 'dynamic_spider'
      allowed_domains = ['example.com']
      start_urls = ['http://example.com']
    
      def start_requests(self):
          yield scrapy.Request('http://example.com',
                               callback=self.parse,
                               meta=dict(
                                   playwright=True,
                                   playwright_page_methods=[
                                       PageMethod('wait_for_selector', 'div.item')
                                   ]
                               ))
    
      def parse(self, response):
          for item in response.css('div.item'):
              yield {
                  'title': item.css('h2 a::text').get(),
                  'link': item.css('h2 a::attr(href)').get(),
                  'desc': item.css('p::text').get()
              }
项目实战演练

实际项目案例分析

根据具体的项目需求,选择合适的爬虫组件和策略。比如抓取特定的新闻网站,可以编写一个Spider来抓取新闻标题、链接和发布时间。

  • 示例代码

    # items.py
    import scrapy
    
    class NewsItem(scrapy.Item):
      title = scrapy.Field()
      link = scrapy.Field()
      pub_date = scrapy.Field()
    
    # spiders/example_spider.py
    import scrapy
    
    from my_project.items import NewsItem
    
    class ExampleSpider(scrapy.Spider):
      name = 'example_spider'
      allowed_domains = ['example.com']
      start_urls = ['http://example.com']
    
      def parse(self, response):
          for news in response.css('div.post'):
              item = NewsItem()
              item['title'] = news.css('h2 a::text').get()
              item['link'] = news.css('h2 a::attr(href)').get()
              item['pub_date'] = news.css('.pub_date::text').get()
              yield item

搭建个人Scrapy项目

搭建一个完整的Scrapy项目,包括定义Spider、处理数据格式和存储。

  • 示例代码

    # items.py
    import scrapy
    
    class NewsItem(scrapy.Item):
      title = scrapy.Field()
      link = scrapy.Field()
      pub_date = scrapy.Field()
    
    # spiders/example_spider.py
    import scrapy
    
    from my_project.items import NewsItem
    
    class ExampleSpider(scrapy.Spider):
      name = 'example_spider'
      allowed_domains = ['example.com']
      start_urls = ['http://example.com']
    
      def parse(self, response):
          for news in response.css('div.post'):
              item = NewsItem()
              item['title'] = news.css('h2 a::text').get()
              item['link'] = news.css('h2 a::attr(href)').get()
              item['pub_date'] = news.css('.pub_date::text').get()
              yield item

项目优化与维护

持续优化和维护爬虫,确保其能够高效且稳定地运行。这包括定期更新Spider代码以适应网站结构的变化,优化数据存储策略,以及监控爬虫性能并及时调整配置。

  • 监控爬虫性能
    • 使用Scrapy自带的命令行工具来监控爬虫。
    • 通过设置LOG_LEVEL来控制日志输出级别。
    • 通过scrapy stats命令获取爬虫运行统计信息。
  • 优化爬虫性能
    • 使用DOWNLOAD_DELAY来避免请求过于频繁。
    • 利用CONCURRENT_REQUESTS_PER_DOMAINCONCURRENT_REQUESTS_PER_IP控制并发数量。
    • 采用合适的请求头设置,如User-AgentAccept-Language,以模拟真实浏览器的行为。
  • 示例代码
    # settings.py
    DOWNLOAD_DELAY = 0.5
    CONCURRENT_REQUESTS_PER_DOMAIN = 16
    CONCURRENT_REQUESTS_PER_IP = 16
    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    ACCEPT_LANGUAGE = 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7'

通过以上步骤和示例代码,新手可以快速从Scrapy的入门到上手,并掌握基本和进阶的功能。希望这些内容能帮助你构建强大的网络爬虫,高效地抓取需要的数据!

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消