介绍
上一篇博客学习的是异步爬虫,打造了爬虫军队,代码要封装为函数形式。
这一篇博客是讲解 scrapy框架,多用于商业爬虫,代码要封装为多文件形式。
Scrapy是基于Twisted开发的,是一个异步的框架,性能是TA最大的优势,在这里我们并不需要手动实现异步的代码......
《目录》
环境配置
回顾一下,爬虫 4 大标准步骤:
- 获取数据 -- requests
- 解析数据 -- bs4
- 提取数据 -- Tag
- 存储数据 -- csv
右边是ta们分别对应的模块/对象,今天我们用 scrapy 代替......
虽然电脑是 Mac,不过我尽量讲全 2 份。
Windows:
- win + R,输入 "cmd"
- pip install scrapy
- 进入到 PyCharm 文件夹(dir...)
- 输入 scrapy startproject name(项目名字,我输入的 dou_ban)
- 用 PyCharm 打开刚刚创建的文件
这个过程可能需要一些 cmd 命令,
接着,用 PyCharm 打开新创建的项目名,整个项目长这样:
就是这么牛皮,不仅文件帮我们创建好了,代码也写了部分.....
Mac:
command + space ,输入 "终端"
- pip3 install virtualenv
- virtualenv venv --python=python3.6
- source venv/bin/activate(启动虚拟环境,每次创建scrapy项目都需要在终端输入ta)
- pip install scrapy
- 进入到 PyCharm 文件夹,接着输入 scrapy startproject name(项目名字,我输入的 dou_ban)
- 用 PyCharm 打开刚刚创建的文件
首先,在 spiders 文件夹里创建一个 file_name.py,这个文件是爬虫的核心即爬虫。
- 获取数据 -- file_name.py
- 解析数据 -- file_name.py
- 提取数据 -- items.py
- 存储数据 -- settings.py
基础样式
下面逐步学习:
假设我们创建的项目是 dou_ban (scrapy startproject dou_ban),在 spiders文件夹创建了 豆瓣电影.py。
接着,再右击 scrapy.crg 创建一个运行dou_ban这个项目的文件(即创建在最外层),名字随意。
p.s. 如果是商业项目, 这个名字建议取为 main,表示ta是主文件。
项目运行
在里面输入启动的代码即可:
from scrapy import cmdline
# 从 scrapy 导入 cmdline 模块
cmdline.execute(['scrapy','crawl','dou_ban'])
# 运行 dou_ban 这个项目
发现,输入后是这样的:
按住 comand + " , ",即打开设置:
接着选择一个 py3 的解释器,并在里面下载 scrapy 模块即可。
召唤爬虫
我们回到 豆瓣电影.py ,在这里面编辑爬虫的核心代码包含 获取数据、解析数据。
今天编辑代码采用 面向对象的风格,因为在 scrapy 框架里面,这样的代码才显得优美。
我先写好代码模版......
获取数据
# 获取数据:定义一个爬虫类DoubanSpider
class DoubanSpider(scrapy.Spider):
# DoubanSpider类继承自scrapy.Spider类
name = 'only name'
# 项目名字,唯一的名字,麻辣小龙虾启动代码的名字
allowed_domains = ['about_URL']
# 只爬与这个URL里相关的网页,比较一般网页都会有广告页
start_urls = ['start_url']
# 从这个URL开始抓取
def parse(self, response):
# 解析数据
print(response.text)
# 不需要写 requests.get(),scrapy框架已经完成,只需要处理服务器响应的即可。
目标数据的URL规律:
第 1 页:https://movie.douban.com/top250?start=0&filter=
第 2 页:https://movie.douban.com/top250?start=25&filter=
发现改变的这是 start= 后面的数字,从 0 开始,步长 25。
利用一个循环即可:
https://book.douban.com/top250?start=' + str(x * 25) + '&filter='
x 是计数器,之后再把数字转为字符,俩段字符合在一起就是完整的URL。
import scrapy
class DoubanSpider(scrapy.Spider):
name = 'dou_ban'
allowed_domains = ['https://movie.douban.com']
start_urls = []
for x in range(10):
url = 'https://movie.douban.com/top250?start=' + str(x * 25) + '&filter='
start_urls.append(url)
这样爬虫第一步获取数据已经完成✅✅
解析数据
解析数据是召唤爬虫模版的第二个函数:parse()
所有电影信息都在 <ol class="grid_view> 里面,每一个子标签 <li> 就是一部电影。
import scrapy, bs4
# 获取数据
class DoubanSpider(scrapy.Spider):
name = 'dou_ban'
allowed_domains = ['https://movie.douban.com']
start_urls = []
for x in range(10):
url = 'https://movie.douban.com/top250?start=' + str(x * 25) + '&filter='
start_urls.append(url)
# 解析数据
def parse(self, response):
# parse是默认处理response的方法
soup = bs4.BeautifulSoup(response.text, 'html.parser')
# 用BeautifulSoup解析response
# 提取数据
min_tag = soup.find('ol', class_="grid_view")
# 所有电影: 最小父级子标签<ol class="grid_view">
for data in min_tag.find_all('li'):
num = data.find('em', class_="").text
name = data.find('span', class_="title").text
comment = data.find('span', class_="rating_num").text
link = data.find('a')['href']
获取数据、解析数据的确是,提取数据却不是这样的。因为这样的风格太紧凑,我们是多文件,怎能把几个步骤都放到一起呢 ?
提取数据
特别是提取数据部分,是爬虫的核心,肯定需要单独处理......
我们把提取数据部分放在 items.py,但为了让 爬虫文件(豆瓣电影.py)与 items.py 相互通信,在items.py中我们使用 scrapy.Field()传递数据,这是 scrapy 自带的传递数据的通道。
import scrapy
class DouBanItem(scrapy.Item):
# 定义一个类DoubanItem,继承自scrapy.Item,item类是框架自带里面有许多实用的属性、方法
num = scrapy.Field()
# 定义电影序号的数据属性
name = scrapy.Field()
# 定义电影名字的数据属性
comment = scrapy.Field()
# 定义电影信息的数据属性
link = scrapy.Field()
# 定义电影链接的数据属性
# items.py 放属性数据,需要什么数据就放什么......
就是怎么简单,这里只需要定义几个提取数据的属性即可。因为是双向通信,豆瓣电影.py(爬虫那个文件),提取数据格式就要改一下,类似字典......
以下是 scrapy 框架的写法,与不用框架写的差距就在这个地方。
from ..items import DouBanItem
# 通信需要引用DouBanItem,ta是items的类。又因为是items在当前文件的上一级目录,所以要用..items,这是一个固定用法。
# 提取数据
min_tag = soup.find('ol', class_="grid_view")
for data in min_tag.find_all('li'):
movie = DouBanItem()
# 创建一个 movie 类,用于通信
movie["num"] = data.find('em', class_="").text
movie["name"] = data.find('span', class_="title").text
movie["comment"] = data.find('span', class_="rating_num").text
movie["link"] = data.find('a')['href']
yield movie
# 用yield语句把item传递给引擎, 如果这个没写就不会传递数据
以下是不用框架写:
# 提取数据
min_tag = soup.find('ol', class_="grid_view")
for data in min_tag.find_all('li'):
num = data.find('em', class_="").text
name = data.find('span', class_="title").text
comment = data.find('span', class_="rating_num").text
link = data.find('a')['href']
那么,整个豆瓣电影.py 代码如下:
import scrapy, bs4
from ..items import DouBanItem
# 需要引用DouBanItem,ta是items的类。又因为是items在当前文件的上一级目录,所以要用..items,这是一个固定用法。
# 获取数据
class DoubanSpider(scrapy.Spider):
name = 'dou_ban'
allowed_domains = ['https://movie.douban.com']
start_urls = []
for x in range(10):
url = 'https://movie.douban.com/top250?start=' + str(x * 25) + '&filter='
start_urls.append(url)
# 解析数据
def parse(self, response):
soup = bs4.BeautifulSoup(response.text, 'html.parser')
# 提取数据
min_tag = soup.find('ol', class_="grid_view")
for data in min_tag.find_all('li'):
movie = DouBanItem()
# 实例化DoubanItem这个类。
movie["num"] = data.find('em', class_="").text
movie["name"] = data.find('span', class_="title").text
movie["comment"] = data.find('span', class_="rating_num").text
movie["link"] = data.find('a')['href']
yield movie
# 用yield语句把item传递给引擎, 如果这个没写就不会传递数据
设置反爬
srcapy框架把设置放在了 settings.py 里,基本帮我们写好了,只需要改动一些参数即可。
修改请求头:删除 USER_AGENT 的注释符号,并加深
user-agent的内容。
e.g.
USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'
更多时候,我们会用到一个第三方库 fake-useragent,随机生成User-Agent,具体安装和用法:
https://github.com/hellysmile/fake-useragent
反 robots协议,将 ROBOTSTXT_OBEY=True
改成 ROBOTSTXT_OBEY=False即可,scrapy默认遵守 robots协议。
e.g.
ROBOTSTXT_OBEY = False
存储数据
在 settings.py 文件加一段代码即可,演示 csv 文件存储:
Windows:
FEED_URI='./storage/data/%(name)s.csv'
FEED_FORMAT='CSV'
FEED_EXPORT_ENCODING='ansi'
Mac:
FEED_URI='./storage/data/%(name)s.csv'
FEED_FORMAT='CSV'
FEED_EXPORT_ENCODING='utf-8'
最后运行 麻辣小龙虾.py 即可。
爬虫完毕,感谢 ! !
接下来,爬虫专题更新多为反爬的内容......
scrapy组成
scrapy整个框架是由 引擎、调度器、下载器、爬虫、数据管道组成。
- 调度器:处理引擎发送过来的requests对象,并把请求的url以有序的方式排列成队,并等待引擎来提取即【异步】。
- 下载中间件:下载器的秘书,会提前对引擎发送的诸多requests做处理 。
- 下载器:处理引擎发送过来的requests,进行网页爬取,并将返回的爬取到的内容(response)交给引擎即【获取数据】。
- 爬虫中间件:爬虫的秘书,会提前接收并处理引擎发送来的爬取到的内容(response),过滤掉一些重复无用的东西。
- 爬虫: 创建requests对象和接受引擎发送过来的下载器爬取到的内容(response),从中解析并提取出有用的数据即【解析、提取】。
- 数据管道:存储和处理爬虫提取到的有用数据即【存储数据】。
描述一下,爬豆瓣的scrapy框架流程:
- 引擎从爬虫那里,得到已经被封装成requests对象的URL。这就是为什么我们不需要写 requests.get 的原因。
- 引擎把requests对象交给了调度器,让ta实现队列完成异步爬虫,scrapy框架快速的原因。
- 引擎再把整个队列交给下载器,下载器火力全开后,把requests爬下来的打包成 response 给引擎。
- 引擎又把打包过的 response 给了爬虫让ta提取,最后给数据管道处理。
组成一个 scrapy项目大致流程:
- 终端创建 scrapy 项目
- 定义 items 的属性
- 编辑 spiders 文件的爬虫代码
- 修改 settings 文件,包含反爬、存储
- 编写 main 文件,运行项目
除了 1 是最先,其余步骤可以不用按照顺序......
settings官方文档 : https://docs.scrapy.org/en/latest/topics/settings.html#std:setting-DOWNLOADER_MIDDLEWARES_BASE
各种语言的爬虫框架:https://www.jianshu.com/p/7522e1fc3fb9