scrapy框架
简介:Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍。所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具有很强通用性的项目模板。对于框架的学习,重点是要学习其框架的特性、各个功能的用法即可。
- 环境安装:
- mac、linux:
- pip install scrapy
- windows:
- pip3 install wheel
- 下载twisted
http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
- 进入下载目录,执行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl
- Twisted:就是一个异步的架构,被作用在了scrapy中
- 安装报错:需要更换另一个版本的twisted文件进行安装即可
- pip3 install pywin32
- pip3 install scrapy
- 安装完成后在cmd中输入scrapy回车,如果没有报错就说明安装成功
- mac、linux:
scrapy的基本使用
创建一个爬虫工程:scrapy startproject proName
进入工程目录创建爬虫源文件:scrapy genspider spiderName www.xxx.com
执行工程:scrapy crawl spiderName
创建一个工程
- scrapy startproject proName
- 目录结构- scrapy.cfg 项目的主配置信息。(真正爬虫相关的配置信息在settings.py文件中)
- items.py 设置数据存储模板,用于结构化数据,如:Django的Model
- pipelines 数据持久化处理
- settings.py 配置文件,如:递归的层数、并发数,延迟下载等
- spiders 爬虫目录,如:创建文件,编写爬虫解析规则
进入工程目录创建爬虫源文件
- scrapy genspider spiderName www.xxx.com
对爬虫源文件编写相应的代码
执行工程
- scrapy crawl spiderName
- 执行工程后,默认会输出工程所有的日志信息
修改工程的配置文件settings.py
- 我们可以指定类型日志的输出
- 在settings.py中加入 LOG_LEVEL = ‘ERROR’
- 禁止robots
- UA 伪装
爬虫文件spiderName内容阐述:
import scrapy
class GpcSpider(scrapy.Spider):
# 爬虫文件的名称,当前源文件的唯一标识
name = 'gpc'
# allowed_domains表示允许的域名,用来限定start_urls那些url可以发请求那些不能
# allowed_domains = ['www.xxx.com'] #我们一般给注释掉
# start_urls起始url列表只可以存储url
#作用:列表中存储的url都会被进行get请求的发送
start_urls = ['https://www.baidu.com/','https://www.sogou.com']
# 数据解析
#parse方法调用的次数取决于start_urls请求的次数
#参数response:表示的就是服务器返回的响应对象
def parse(self, response):
pass
scrapy数据解析
- 使用:response.xpath(“xpath表达式解析数据”)
- scrapy封装的xpath和etree中的区别
- scrapy中的xpath直接将定位到的标签中存储的值或者属性值取出,返回的是Selector对象,且相关的数据值是存储在Selector对象的data中,需要调用extract(),extract_first()取出字符串数据
爬虫源文件代码如下
import scrapy
class GpcSpider(scrapy.Spider):
# 爬虫文件的名称,当前源文件的唯一标识
name = 'gpc'
# allowed_domains表示允许的域名,用来限定start_urls那些url可以发请求那些不能
# allowed_domains = ['www.xxx.com'] #我们一般给注释掉
# start_urls起始url列表只可以存储url
#作用:列表中存储的url都会被进行get请求的发送
start_urls = ['https://duanziwang.com/category/经典段子/']
# 数据解析
#parse方法调用的次数取决于start_urls请求的次数
#参数response:表示的就是服务器返回的响应对象
def parse(self, response):
# 数据解析名称和内容
article_list = response.xpath('//*[@id="35087"]')
for article in article_list:
# scrapy的xpath和etree中xpath使用方式不同
# xpath返回的列表中存储是Selector对象,说明我们想要的字符串数据被存储在了该对象的data属性中
#extract()就是将data属性值取出
# 调用extract_first() 将列表中第一个列表元素表示的Selector对象中的data值取出
#title = article.xpath("//div[@class='post-head']/h1[@class='post-title']/a/text()").extract_first()
#content = article.xpath("//div[@class='post-content']/p/text()").extract_first()
# 直接调用extract(),可以将列表中的每一个列表元素取出
title = article.xpath("//div[@class='post-head']/h1[@class='post-title']/a/text()").extract()
content = article.xpath("//div[@class='post-content']/p/text()").extract()
# 将Selector对象data属性值取出
print(title,content)
持久化存储
基于终端指令持久化存储
-
该种方式只可以将parse方法的返回值存储到本地指定后缀的文本文件中
-
执行指令:scrapy crawl spiderName -o filePath
- 代码如下:
import scrapy
class GpcSpider(scrapy.Spider):
# 爬虫文件的名称,当前源文件的唯一标识
name = 'gpc'
# allowed_domains表示允许的域名,用来限定start_urls那些url可以发请求那些不能
# allowed_domains = ['www.xxx.com'] #我们一般给注释掉
# start_urls起始url列表只可以存储url
#作用:列表中存储的url都会被进行get请求的发送
start_urls = ['https://duanziwang.com/category/经典段子/']
# 数据解析
#parse方法调用的次数取决于start_urls请求的次数
#参数response:表示的就是服务器返回的响应对象
# 基于终端指令的持久化存储
def parse(self, response):
all_data = []
# 数据解析名称和内容
article_list = response.xpath('//*[@id="35087"]')
for article in article_list:
# 我们可以看见解析出来的内容不是字符串数据,说明和etree中xpath使用方式不同
# xpath返回的列表中存储是Selector对象,说明我们想要的字符串数据被存储在了该对象的data属性中
#extract()就是将data属性值取出
# 调用extract_first() 将列表中第一个列表元素表示的Selector对象中的data值取出
#title = article.xpath("//div[@class='post-head']/h1[@class='post-title']/a/text()").extract_first()
#content = article.xpath("//div[@class='post-content']/p/text()").extract_first()
# 直接调用extract(),可以将列表中的每一个列表元素取出
title = article.xpath("//div[@class='post-head']/h1[@class='post-title']/a/text()").extract()
content = article.xpath("//div[@class='post-content']/p/text()").extract()
# 将Selector对象data属性值取出
print(title,content)
dic = {
"title":title,
"content":content
}
all_data.append(dic)
return all_data
基于管道的持久化存储(重点)
1,在爬虫文件中进行数据解析
2,在items.py中定义相关属性
3,在爬虫文件中将解析到的数据存储封装到 item类型的对象中
4,将item类型的对象提交给管道
5,在管道文件(pipelines.py)中,接受爬虫文件提交过来的item类型对象,且对其进行任意形式的持久化存储
6,在配置文件中开启管道机制
7,展示一(extract_first())
import scrapy
from gemoumou.items import GemoumouItem
class GpcSpider(scrapy.Spider):
# 爬虫文件的名称,当前源文件的唯一标识
name = 'gpc'
# allowed_domains表示允许的域名,用来限定start_urls那些url可以发请求那些不能
# allowed_domains = ['www.xxx.com'] #我们一般给注释掉
# start_urls起始url列表只可以存储url
#作用:列表中存储的url都会被进行get请求的发送
start_urls = ['https://duanziwang.com/category/经典段子/']
# 数据解析
#parse方法调用的次数取决于start_urls请求的次数
#参数response:表示的就是服务器返回的响应对象
# 基于管道的持久化存储
def parse(self, response):
# 数据解析名称和内容
article_list = response.xpath('//*[@id="35087"]')
for article in article_list:
# 我们可以看见解析出来的内容不是字符串数据,说明和etree中xpath使用方式不同
# xpath返回的列表中存储是Selector对象,说明我们想要的字符串数据被存储在了该对象的data属性中
# extract()就是将data属性值取出
# 直接调用extract(),可以将列表中的每一个列表元素取出
title = article.xpath("//div[@class='post-head']/h1[@class='post-title']/a/text()").extract_first()
content = article.xpath("//div[@class='post-content']/p/text()").extract_first()
# 实例化一个item类型的对象,将解析到的数据存储到该对象中
item = GemoumouItem()
# 不能使用item. 来调用数据
item['title'] = title
item['content'] = content
# 将item对象提交给管道
yield item
8,展示二(extract())
import scrapy
from gemoumou.items import GemoumouItem
class GpcSpider(scrapy.Spider):
# 爬虫文件的名称,当前源文件的唯一标识
name = 'gpc'
# allowed_domains表示允许的域名,用来限定start_urls那些url可以发请求那些不能
# allowed_domains = ['www.xxx.com'] #我们一般给注释掉
# start_urls起始url列表只可以存储url
#作用:列表中存储的url都会被进行get请求的发送
start_urls = ['https://duanziwang.com/category/经典段子/']
# 数据解析
#parse方法调用的次数取决于start_urls请求的次数
#参数response:表示的就是服务器返回的响应对象
# 基于管道的持久化存储
def parse(self, response):
# 数据解析名称和内容
article_list = response.xpath('//*[@id="35087"]')
for article in article_list:
# 我们可以看见解析出来的内容不是字符串数据,说明和etree中xpath使用方式不同
# xpath返回的列表中存储是Selector对象,说明我们想要的字符串数据被存储在了该对象的data属性中
# extract()就是将data属性值取出
# 直接调用extract(),可以将列表中的每一个列表元素取出
title_content_list = article.xpath("//div[@class='post-head']/h1[@class='post-title']/a/text() | //div[@class='post-content']/p/text()").extract()
# 实例化一个item类型的对象,将解析到的数据存储到该对象中
item = GemoumouItem()
for title_content in title_content_list:
# 不能使用item. 来调用数据
item['title_content'] = title_content
# 将item对象提交给管道
yield item