记得 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
2. 设置待抓取内容的字段, 本例中就是文章的标题, 地址和摘要
修改 items.py 文件, 在 MyCrawlerItem 类中加上如下代码:
- # -*- coding: utf-8 -*-
- import scrapy
- class MyCrawlerItem(scrapy.Item):
- title = scrapy.Field() # 文章标题
- url = scrapy.Field() # 文章地址
- summary = scrapy.Field() # 文章摘要
- pass
3. 编写网页解析代码
在 my_crawler/spiders 目录下, 创建一个名为 crawl_spider.py 文件 (文件名可以任意取) 代码如下
- # -*- 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
4. 让我们测试下爬虫的效果
在命令行中输入:
$ 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 可以省去)
5. 将结果保存到数据库
这里我们采用 MongoDB, 你需要先安装 Python 的 MongoDB 库 pymongo 编辑 my_crawler 目录下的 pipelines.py 文件, 在 MyCrawlerPipeline 类中加上如下代码:
- # -*- 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 的设置:
- ITEM_PIPELINES = {
- 'my_crawler.pipelines.MyCrawlerPipeline': 300, # 设置 Pipeline, 可以多个, 值为执行优先级
- }
- # MongoDB 连接信息
- MONGO_SERVER = 'localhost'
- MONGO_PORT = 27017
- MONGO_DB = 'bjhee'
- MONGO_COLLECTION = 'articles'
- DOWNLOAD_DELAY=2 # 如果网络慢, 可以适当加些延迟, 单位是秒
6. 执行爬虫
$ scrapy crawl my_crawler
别忘了启动 MongoDB 并创建 bjhee 数据库哦现在你可以在 MongoDB 里查询到记录了
总结下, 使用 Scrapy 来构建一个网络爬虫, 你需要做的就是:
items.py 中定义爬取字段在 spiders 目录下创建你的爬虫, 编写解析函数和规则 pipelines.py 中对爬取后的结果做处理 settings.py 设置必要的参数
其他的事情, Scrapy 都帮你做了下图就是 Scrapy 具体工作的流程怎么样? 开始写一个自己的爬虫吧
本例中的代码可以在这里下载 http://www.jqhtml.com/wp-content/uploads/2018/02/wz/my_crawler.tar.gz
来源: http://www.jqhtml.com/10941.html