「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」
Scrapy爬虫框架
scrapy是什么
它是一个快速功能强大的开源网络爬虫框架
Github地址:github.com/scrapy/scra…
官网地址:scrapy.org/
scrapy的安装
cmd上运行
pip install scrapy
测试: scrapy -h
一般直接pip install scrapy会出错,可参考:【转】
blog.csdn.net/qq_42543250…
安装成功后测试会(scrapy -h):
Scrapy爬虫框架结构
“5+2”结构
框架组件:
| 组件 | 作用 |
|---|---|
| Scrapy Engine | 引擎,处理整个框架的数据流 |
| Scheduler | 调度器,接收引擎发过来的请求,将其排至队列中,当引擎再次请求时返回 |
| Downloader | 下载器,下载所有引擎发送的请求,并将获取的源代码返回给引擎,之后由引擎交给爬虫处理 |
| Spiders | 爬虫,接收并处理所有引擎发送过来的源代码,从中分析并提取item字段所需要的数据,并将需要跟进的url提交给引擎,再次进入调度器 |
| Item Pipeline | 管道,负责处理从爬虫中获取的Item,并进行后期处理 |
| Downloader Middlewares | 下载中间件,可以理解为自定义扩展下载功能的组件 |
| Spider Middlewares | Spider中间件,自定义扩展和操作引擎与爬虫之间通信的功能组件 |
Scrapy爬虫的数据类型
- Request类
- Response类
- Item类
Scrapy数据处理流程:
- 当需要打开一个域名时,爬虫开始获取第一个url,并返回给引擎
- 引擎把url作为一个请求交给调度器
- 引擎再次对调度器发出请求,并接收上一次让调度器处理的请求
- 引擎将请求交给下载器
- 下载器下载完成后,作为响应返回给引擎
- 引擎把响应交给爬虫,爬虫开始进一步处理,处理完成后有两个数据,一个是需要跟进的url,另一个是获取到的item数据,然后把结果返回给引擎
- 引擎把需要跟进的url给调度器,把获取的item数据给管道
- 然后从第2步开始循环,知道获取信息完毕。只有调度器中没有任何请求时,程序才会停止
Scrapy爬虫的基本使用
yield关键字的使用
- 包含yield语句的函数是一个生成器
- 生成器每次产生一个值(yield语句),函数被冻结,被唤醒后再产生一个值
- 生成器是一个不断产生值的函数
Scrapy爬虫的常用命令
| 命令 | 说明 | 格式 |
|---|---|---|
| startproject | 创建一个新工程 | scrapy startproject projectName |
| genspider | 创建一个爬虫 | scrapy genspider [options]name domain |
| settings | 获得爬虫配置信息 | scrapy settings [options] |
| crawl | 运行一个爬虫 | scrapy crawl spider |
| list | 列出工程中所有爬虫 | scrapy list |
| shell | 启动URL调试命令行 | scrapy shell [url] |
Scrapy爬虫的使用步骤
- 新建项目 (scrapy startproject xxx):新建一个新的爬虫项目
创建工程:scrapy startproject mydemo
目录树:
工程目录下各个文件的作用
| 文件 | 作用 |
|---|---|
| scrapy.cfg | 配置文件 |
| spiders | 存放你Spider文件,也就是你爬取的py文件 |
| items.py | 相当于一个容器,和字典较像 |
| middlewares.py | 定义Downloader Middlewares(下载器中间件)和Spider Middlewares(蜘蛛中间件)的实现 |
| pipelines.py | 定义Item Pipeline的实现,实现数据的清洗,储存,验证。 |
| settings.py | 全局配置 |
- 明确目标 (编写items.py):明确你想要抓取的目标
items.py文件内容
- 制作爬虫 (spiders/xxspider.py):制作爬虫开始爬取网页
Spider爬虫模板:
- 存储内容 (pipelines.py):设计管道存储爬取内容
实例:豆瓣Top250信息-Scrapy爬虫
创建工程:
scrapy startproject douban
在douban目录下:
scrapy genspider douban_scrapy douban.com
明确目标
我们打算抓取movie.douban.com/top250
网站里的所有电影的序号、名称、介绍、评分、评论数、描述
打开 douban 目录下的 items.py。
Item 定义结构化数据字段,用来保存爬取到的数据,有点像 Python 中的 dict,但是提供了一些额外的保护减少错误。
可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field 的类属性来定义一个 Item(可以理解成类似于 ORM 的映射关系)。
接下来,创建一个 ItcastItem 类,和构建 item 模型(model)。
复制代码
items.py
import scrapy
class DoubanItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 电影序号
serial_number = scrapy.Field()
# 电影名称
movie_name = scrapy.Field()
# 电影介绍
introduce = scrapy.Field()
# 电影星级
star = scrapy.Field()
# 电影评论数
evaluate = scrapy.Field()
# 电影描述
describe = scrapy.Field()
复制代码
制作爬虫 (spiders/douban_scrapy.py)
在当前目录下输入命令,将在mySpider/spider目录下创建一个名为itcast的爬虫,并指定爬取域的范围:
scrapy genspider douban_scrapy movie.douban.com
打开 douban/spider目录里的 douban_scrapy.py,默认增加了下列代码:
#douban_scrapy.py
#-*- coding: utf-8 -*-
import scrapy
from douban.items import DoubanItem
class DoubanScrapySpider(scrapy.Spider):
name = 'douban_scrapy'
allowed_domains = ['movie.douban.com']
start_urls = ['https://movie.douban.com/top250']
def parse(self, response): # 解析的方法
# movie_list 的类型为<class 'scrapy.selector.unified.SelectorList'>
movie_list = response.xpath("//ol[@class ='grid_view']/li")
# 数据的查找
# self.log('movie_list 的类型为{}
for i_item in movie_list:
# item文件的导入
douban_item = DoubanItem()
# 数据的筛选
#extract():这个方法返回的是一个数组list,,里面包含了多个string,如果只有一个string,则返回['ABC']这样的形式。
#extract_first():这个方法返回的是一个string字符串,是list数组里面的第一个字符串。
douban_item['serial_number'] = i_item.xpath(".//div[@class='pic']/em/text()").extract_first()
douban_item['movie_name'] = i_item.xpath(".//div[@class='hd']/a/span[1]/text()").extract_first()
douban_item['introduce'] = i_item.xpath(".")
content = i_item.xpath(".//div[@class='bd']/p[1]/text()").extract()
for i_content in content:
contents = "".join(i_content.split())
douban_item['introduce'] = contents
douban_item['star'] = i_item.xpath(".//div[@class='star']/span[2]/text()").extract_first()
douban_item['evaluate'] = i_item.xpath(".//div[@class='star']/span[4]/text()").extract_first()
douban_item['describe'] = i_item.xpath(".//p[@class= 'quote']/span/text()").extract_first()
#将数据返回到pipeline,用生成器
yield douban_item
next_link = response.xpath("//span[@class ='next']/link/@href").extract()
# 解析下一页,规则,取后一页的xpath
if next_link:
next_link = next_link[0]
#Spider产生下一页的Request请求
yield scrapy.Request('https://movie.douban.com/top250'+next_link,callback=self.parse)
复制代码
保存数据 (pipeline.py)
一.scrapy保存信息的最简单的方法主要有四种,-o 输出指定格式的文件,命令如下:
scrapy crawl douban_scrapy -o douban.json
json lines格式,默认为Unicode编码
scrapy crawl douban_scrapy -o douban.jsonl
csv 逗号表达式,可用Excel打开
scrapy crawl douban_scrapy -o douban.csv
xml格式
scrapy crawl douban_scrapy -o douban.xml
二、通过pipeline存储进mysql
pipeline.py
import pymysql
from twisted.enterprise import adbapi
from scrapy import log
class DoubanPipeline(object):
#使用teisted异步存储
def __init__(self, dbpool):
self.dbpool = dbpool
@classmethod
def from_settings(cls, settings):
dbparms = {
'host': "localhost",
'user': "root",
'port': 3306,
'passwd': "root",
'db': "mystudy",
'charset': 'utf8',
'cursorclass': pymysql.cursors.DictCursor,
'use_unicode': True
}
dbpool = adbapi.ConnectionPool('pymysql', **dbparms)
return cls(dbpool)
def process_item(self, item, spider):
# 使用Twisted 将MYSQL 插入变成异步执行
# runInteraction 第一个参数是一个函数
query = self.dbpool.runInteraction(self.do_insert, item)
query.addCallback(self.handle_error, item, spider) # 处理异常
return item
def handle_error(self, failure, item, spider):
# 处理异步插入的异常
print(failure)
def do_insert(self, cursor, item):
# 执行具体的插入
insert_sql = '''
insert into douban (serial_number,movie_name,introduce,star, evaluate,Mdescribe) values (%s, %s, %s, %s, %s, %s);
'''
cursor.execute(insert_sql,
(item['serial_number'], item['movie_name'], item['introduce'], item['star'], item['evaluate'],item['describe']))
复制代码
一些配置
#settings.py
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
ROBOTSTXT_OBEY = False
ITEM_PIPELINES = {
'douban.pipelines.DoubanPipeline':10
}
复制代码




近期评论