zoukankan      html  css  js  c++  java
  • 使用Scrapy构建一个网络爬虫

    记得n年前项目需要一个灵活的爬虫工具,就组织了一个小团队用Java实现了一个爬虫框架,可以根据目标网站的结构、地址和需要的内容,做简单的配置开发,即可实现特定网站的爬虫功能。因为要考虑到各种特殊情形,开发还耗了不少人力。后来发现了Python下有这个Scrapy工具,瞬间觉得之前做的事情都白费了。对于一个普通的网络爬虫功能,Scrapy完全胜任,并把很多复杂的编程都包装好了。本文会介绍如何Scrapy构建一个简单的网络爬虫。
    一个基本的爬虫工具,它应该具备以下几个功能:
    • 通过HTTP(S)请求,下载网页信息
    • 解析网页,抓取需要的内容
    • 保存内容
    • 从现有页面中找到有效链接,从而继续抓取下一个网页
    我们来看下Scrapy怎么做到这些功能的。首先准备Scrapy环境,你需要安装Python(本文使用v2.7)和pip,然后用pip来安装lxml和scrapy。个人强烈建议使用virtualenv来安装环境,这样不同的项目之间不会冲突。详细步骤这里就不赘述了。对于Mac用户要注意,当使用pip安装lxml时,会出现类似于的下面错误:
    Error: #include “xml/xmlversion.h” not found
    解决这个问题,你需要先安装Xcode的command line tools,具体的方法是在命令行执行下面的命令即可。
    $ xcode-select --install
    环境安装好之后,我们来用Scrapy实现一个简单的爬虫,抓取本博客网站的文章标题,地址和摘要。
      1. 创建工程
    $ scrapy startproject my_crawler
    该命令会在当前目录下创建一个名为”my_crawler”的工程,工程的目录结构如下
    my_crawler
      |- my_crawler
      |    |- spiders
      |    |    |- __init__.py
      |    |- items.py
      |    |- pipelines.py
      |    |- setting.py
      |- scrapy.cfg
     
      1. 设置待抓取内容的字段,本例中就是文章的标题,地址和摘要
    修改”items.py”文件,在”MyCrawlerItem”类中加上如下代码:
    1
    2
    3
    4
    5
    6
    7
    8
    # -*- coding: utf-8 -*-
    import scrapy
     
    class MyCrawlerItem(scrapy.Item):
        title = scrapy.Field()    # 文章标题
        url = scrapy.Field()      # 文章地址
        summary = scrapy.Field()  # 文章摘要
        pass
      1. 编写网页解析代码
    在”my_crawler/spiders”目录下,创建一个名为”crawl_spider.py”文件(文件名可以任意取)。代码如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    # -*- coding: utf-8 -*-
    import scrapy
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider, Rule
     
    from my_crawler.items import MyCrawlerItem
     
    class MyCrawlSpider(CrawlSpider):
        name = 'my_crawler'               # Spider名,必须唯一,执行爬虫命令时使用
        allowed_domains = ['bjhee.com']   # 限定允许爬的域名,可设置多个
        start_urls = [
            "http://www.bjhee.com",       # 种子URL,可设置多个
        ]
     
        rules = (    # 对应特定URL,设置解析函数,可设置多个
            Rule(LinkExtractor(allow=r'/page/[0-9]+'),  # 指定允许继续爬取的URL格式,支持正则
                               callback='parse_item',   # 用于解析网页的回调函数名
                               follow=True
            ),
        )
     
        def parse_item(self, response):
            # 通过XPath获取Dom元素
            articles = response.xpath('//*[@id="main"]/ul/li')
     
            for article in articles:
                item = MyCrawlerItem()
                item['title'] = article.xpath('h3[@class="entry-title"]/a/text()').extract()[0]
                item['url'] = article.xpath('h3[@class="entry-title"]/a/@href').extract()[0]
                item['summary'] = article.xpath('div[2]/p/text()').extract()[0]
                yield item
    对于XPath不熟悉的朋友,可以通过Chrome的debug工具获取元素的XPath。
     
      1. 让我们测试下爬虫的效果
    在命令行中输入:
    $ scrapy crawl my_crawler
    注意,这里的”my_crawler”就是你在”crawl_spider.py”文件中起的Spider名。
    没过几秒钟,你就会看到要抓取的字段内容打印在控制台上了。就是这么神奇!Scrapy将HTTP(S)请求,内容下载,待抓取和已抓取的URL队列的管理都封装好了。你的主要工作基本上就是设置URL规则及编写解析的方法。
    我们将抓取的内容保存为JSON文件:
    $ scrapy crawl my_crawler -o my_crawler.json -t json
    你可以在当前目录下,找到文件”my_crawler.json”,里面保存的就是我们要抓取的字段信息。(参数”-t json”可以省去)
      1. 将结果保存到数据库
    这里我们采用MongoDB,你需要先安装Python的MongoDB库”pymongo”。编辑”my_crawler”目录下的”pipelines.py”文件,在”MyCrawlerPipeline”类中加上如下代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    # -*- coding: utf-8 -*-
    import pymongo
     
    from scrapy.conf import settings
    from scrapy.exceptions import DropItem
     
    class MyCrawlerPipeline(object):
        def __init__(self):
            # 设置MongoDB连接
            connection = pymongo.Connection(
                settings['MONGO_SERVER'],
                settings['MONGO_PORT']
            )
            db = connection[settings['MONGO_DB']]
            self.collection = db[settings['MONGO_COLLECTION']]
     
        # 处理每个被抓取的MyCrawlerItem项
        def process_item(self, item, spider):
            valid = True
            for data in item:
                if not data:  # 过滤掉存在空字段的项
                    valid = False
                    raise DropItem("Missing {0}!".format(data))
     
            if valid:
                # 也可以用self.collection.insert(dict(item)),使用upsert可以防止重复项
                self.collection.update({'url': item['url']}, dict(item), upsert=True)
     
            return item
    再打开”my_crawler”目录下的”settings.py”文件,在文件末尾加上pipeline的设置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ITEM_PIPELINES = {
        'my_crawler.pipelines.MyCrawlerPipeline': 300,    # 设置Pipeline,可以多个,值为执行优先级
    }
     
    # MongoDB连接信息
    MONGO_SERVER = 'localhost'
    MONGO_PORT = 27017
    MONGO_DB = 'bjhee'
    MONGO_COLLECTION = 'articles'
     
    DOWNLOAD_DELAY=2    # 如果网络慢,可以适当加些延迟,单位是秒
      1. 执行爬虫
    $ scrapy crawl my_crawler
    别忘了启动MongoDB并创建”bjhee”数据库哦。现在你可以在MongoDB里查询到记录了。
     
    总结下,使用Scrapy来构建一个网络爬虫,你需要做的就是:
    • “items.py”中定义爬取字段
    • 在”spiders”目录下创建你的爬虫,编写解析函数和规则
    • “pipelines.py”中对爬取后的结果做处理
    • “settings.py”设置必要的参数
    其他的事情,Scrapy都帮你做了。下图就是Scrapy具体工作的流程。怎么样?开始写一个自己的爬虫吧。
     
    本例中的代码可以在这里下载(http://www.bjhee.com/downloads/201511/my_crawler.tar.gz)。
  • 相关阅读:
    python入门-函数(二)
    python入门-函数(一)
    python入门-WHILE循环
    python入门-用户输入
    python入门-字典
    Spring Security授权 AccessDecisionManager
    Java的性能优化
    datahub
    vbs mytest
    spring发布和接收定制的事件(spring事件传播)
  • 原文地址:https://www.cnblogs.com/allan-king/p/7094930.html
Copyright © 2011-2022 走看看