在上一篇文章中,我们简单学习了如何用requests库进行简单的爬虫,对于数据量较小的数据爬取,可以使用这种方式进行爬虫。
但如果要爬取的数据量较大,对性能有一定要求的话,就需要使用一些爬虫框架了。(其实requests+各种解析器已经较为好用了,但对于比较通用性的爬虫,框架可以提高效率,不用写那么多代码)
本篇文章来学习一下较常用的爬虫框架scrapy的使用
scrapy框架介绍
比较流行的爬虫的框架有scrapy
和pyspider
,scrapy
的使用可能更广一些。
scrapy
是一个开源的高级爬虫框架,使用python
编写,用于爬取网页,提取结构性数据,并可将抓取得结构性数据较好的应用于数据分析和数据挖掘。
scrapy
有以下的一些特点:
scrapy
基于事件的机制,利用twisted
的设计实现了非阻塞的异步操作。这相比于传统的阻塞式请求,极大的提高了CPU的使用率,以及爬取效率。- 配置简单,可以简单的通过设置一行代码实现复杂功能。
- 可拓展,插件丰富,比如分布式
scrapy + redis
、爬虫可视化等插件。 - 解析方便易用,
scrapy
封装了xpath
等解析器,提供了更方便更高级的selector
构造器,可有效的处理破损的HTML
代码和编码。
使用方式
1、安装 Scrapy
pip install scrapy
2、创建一个scrapy项目(提取进到你要放这个项目的路径)
scrapy startproject spider_test
3、自动生成的项目的代码结构如下图
- scrapy.cfg: 项目的配置文件。
- items.py: 项目的目标文件。
- pipelines.py: 项目的管道文件。
- settings.py: 项目的设置文件。
- spiders/: 存储爬虫代码目录。
4、爬取数据 假如我们要爬取豆瓣电影的top250的电影名,电影类型,以及海报url
4.1 创建一个Item Item 是保存爬取到的数据的容器;其使用方法和python字典类似, 并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。
类似在ORM中做的一样,您可以通过创建一个 scrapy.Item
类, 并且定义类型为 scrapy.Field
的类属性来定义一个Item。
首先我们创建一个filmItem(在items.py 中增加一下代码)
class FilmItem(scrapy.Item):
name = scrapy.Field()
type = scrapy.Field()
img = scrapy.Field()
4.2 在命令行执行
scrapy genspider FilmItem "movie.douban.com/top250"
自动生成爬虫模版代码(也可以自己写,主要就是创建一个spider类)
name
: 用于区别Spider,该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。start_urls
: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。parse()
:是spider的一个方法。 被调用时,每个初始URL完成下载后生成的Response
对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的Request
对象。
4.3 修改starts_url为要爬取的url
4.4 利用xpath规则提取响应数据
def parse(self, response):
for li in response.xpath("//ol[@class='grid_view']/li"):
item = FilmItem()
item['name'] = li.xpath(".//div[@class='hd']/a/span[@class='title']/text()").extract_first()
item['type'] = li.xpath(".//div[@class='hd']/a/span[@class='other']/text()").extract_first()
item['img'] = li.xpath(".//div[@class='pic']/a/img/@src").extract_first()
yield item
xpath 规则需要另外学习一下
4.5 开始爬虫 整个FilmItem的代码如下,import的路径需要根据你的使用修改一下
import scrapy
import sys
sys.path.append("/Users/***/PycharmProjects/web Spider/step_2_framework/spider_test/spider_test/")
from items import FilmItem
from scrapy import Request
class FilmitemSpider(scrapy.Spider):
name = 'FilmItem'
allowed_domains = ['movie.douban.com']
start_urls = ['https://movie.douban.com/top250/']
def start_requests(self):
for i in range(10):
url = f'https://movie.douban.com/top250?start={25 * i}&filter='
yield Request(url=url, callback=self.parse)
def parse(self, response):
for li in response.xpath("//ol[@class='grid_view']/li"):
item = FilmItem()
item['name'] = li.xpath(".//div[@class='hd']/a/span[@class='title']/text()").extract_first()
item['type'] = li.xpath(".//div[@class='hd']/a/span[@class='other']/text()").extract_first()
item['img'] = li.xpath(".//div[@class='pic']/a/img/@src").extract_first()
yield item
ps.在获取页面之前scrapy先访问了robots.txt
文件,这是一个良好的爬虫习惯,此时scrapy的所有页面获取都将会遵从robots.txt
里面的规则,如果你不想遵从这一规则可以在settings
里配置ROBOTSTXT_OBEY = False
4.6 配置 setting.py文件中增加两天配置
ROBOTSTXT_OBEY = False
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36'
4.7 执行爬虫
scrapy crawl FilmItem -o items.csv
将爬取到的数据保存到csv文件中
感觉使用起来也并没有使用request+解析器方便多少