爬虫技术-Scrapy框架介绍
作者:互联网
Scrapy
采集框架
1 学习目标
1、框架流程和结构设计原理
2、框架爬虫程序编写
3、框架日志模块使用
4、框架请求发送流程
2 scrapy
简介
Scrapy
是用纯Python
实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便。
2.0 单个爬虫编写
class Spider(object):
def __init__(self):
# 负责全局配置
pass
def url_list(self):
# 负责任务池维护
pass
def request(self):
# 负责网络请求模块
pass
def parse(self):
# 负责解析数据模块
pass
def save(self):
# 负责数据存储
pass
def run(self):
# 负责模块调度
pass
2.1 架构介绍
2.2.1 名词解析
2.2.2 运行逻辑图
3 框架使用
3.1 项目搭建
3.1.1 框架安装
查找历史版本:https://pypi.org/project/Scrapy/#history
pip install scrapy==2.3.0
3.1.2 项目创建
scrapy startproject xxxx
文件介绍
- scrapy.cfg:它是 Scrapy 项目的配置文件,其内定义了项目的配置文件路径、部署相关信息等内容。
- items.py:它定义 Item 数据结构,所有的 Item 的定义都可以放这里。
- pipelines.py:它定义 Item Pipeline 的实现,所有的 Item Pipeline 的实现都可以放这里。
- settings.py:它定义项目的全局配置。
- middlewares.py:它定义 Spider Middlewares 和 Downloader Middlewares 的实现。
- spiders:其内包含一个个 Spider 的实现,每个 Spider 都有一个文件。
3.1.3 创建爬虫
Spider
是自己定义的类,Scrapy
用它来从网页里抓取内容,并解析抓取的结果。不过这个类必须继承 Scrapy
提供的 Spider
类 scrapy.Spider
,还要定义 Spider
的名称和起始请求,以及怎样处理爬取后的结果的方法
cd 项目路径
scrapy genspider 爬虫名称 目标地址
配置文件简介
# Scrapy settings for ScrapyDemo project
# 自动生成的配置,无需关注,不用修改
BOT_NAME = 'ScrapyDemo'
SPIDER_MODULES = ['ScrapyDemo.spiders']
NEWSPIDER_MODULE = 'ScrapyDemo.spiders'
# 设置UA,但不常用,一般都是在MiddleWare中添加
USER_AGENT = 'ScrapyDemo (+http://www.yourdomain.com)'
# 遵循robots.txt中的爬虫规则,很多人喜欢False,当然我也喜欢....
ROBOTSTXT_OBEY = True
# 对网站并发请求总数,默认16
CONCURRENT_REQUESTS = 32
# 相同网站两个请求之间的间隔时间,默认是0s。相当于time.sleep()
DOWNLOAD_DELAY = 3
# 下面两个配置二选一,但其值不能大于CONCURRENT_REQUESTS,默认启用PER_DOMAIN
# 对网站每个域名的最大并发请求,默认8
CONCURRENT_REQUESTS_PER_DOMAIN = 16
# 默认0,对网站每个IP的最大并发请求,会覆盖上面PER_DOMAIN配置,
# 同时DOWNLOAD_DELAY也成了相同IP两个请求间的间隔了
CONCURRENT_REQUESTS_PER_IP = 16
# 禁用cookie,默认是True,启用
COOKIES_ENABLED = False
# 请求头设置,这里基本上不用
DEFAULT_REQUEST_HEADERS = {
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# 'Accept-Language': 'en',
}
# 配置启用Spider MiddleWares,Key是class,Value是优先级
SPIDER_MIDDLEWARES = {
'ScrapyDemo.middlewares.ScrapydemoSpiderMiddleware': 543,
}
# 配置启用Downloader MiddleWares
DOWNLOADER_MIDDLEWARES = {
'ScrapyDemo.middlewares.ScrapydemoDownloaderMiddleware': 543,
}
# 配置并启用扩展,主要是一些状态监控
EXTENSIONS = {
'scrapy.extensions.telnet.TelnetConsole': None,
}
# 配置启用Pipeline用来持久化数据
ITEM_PIPELINES = {
'ScrapyDemo.pipelines.ScrapydemoPipeline': 300,
}
3.2 执行爬虫
3.2.1 终端运行爬虫
- 需要去到项目跟路径执行指令
scrapy crawl xxxx
3.2.2 脚本运行
- 在
Scrapy
中有一个可以控制终端命令的模块cmdline
。导入了这个模块,我们就能操控终端 execute
方法能执行终端的命令行
from scrapy import cmdline
cmdline.execute("scrapy crawl xxxx".split())
cmdline.execute(["scrapy","crawl","xxxx"])
运行报错
ImportError: cannot import name 'HTTPClientFactory' from 'twisted.web.client' (unknown location)
解决:
# 降低Twisted版本
pip install Twisted==20.3.0
3.3 scrapy shell
调试
基本使用
scrapy shell https://dig.chouti.com/
数据提取
datas =res.xpath('//div[@class="link-con"]/div')
for i in datas:
print(i.xpath('.//a[@class="link-title link-statistics"]/text()').extract_first())
4 实战演示
4.1 spider结构
import scrapy
from scrapy import cmdline
import bs4
class TopSpider(scrapy.Spider):
name = 'top'
# allowed_domains = ['top.com']
start_urls = ['https://book.douban.com/top250?start=0']
def parse(self, response):
#print(response.text)
bs = bs4.BeautifulSoup(response.text, 'html.parser')
datas = bs.find_all('tr', class_="item")
for data in datas:
item = {}
item['title'] = data.find_all('a')[1]['title']
item['publish'] = data.find('p', class_='pl').text
item['score'] = data.find('span', class_='rating_nums').text
print(item)
if __name__ == '__main__':
cmdline.execute('scrapy crawl top'.split())
4.2 定义数据
在scrapy
中,我们会专门定义一个用于记录数据的类
import scrapy
class DoubanItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field()
#定义书名的数据属性
publish = scrapy.Field()
#定义出版信息的数据属性
score = scrapy.Field()
scrapy.Field()
这行代码实现的是,让数据能以类似字典的形式记录。但记录的方式却不是字典,是是我们定义的DoubanItem
,属于“自定义的Python
字典”。
4.3 定义管道存储
4.3.1 配置管道
放开配置文件
ITEM_PIPELINES = {
'douban.pipelines.DoubanPipeline': 300,
}
4.3.2 存储文件编写
import json
class DoubanPipeline:
def process_item(self, item, spider):
with open('da.json', 'a+', encoding='utf-8') as f:
f.write(json.dumps(dict(item), ensure_ascii=False))
f.write('\r\n')
4.3.3 配置日志
配置日志来做记录
LOG_LEVEL = 'WARNING'
LOG_FILE = './log.log'
配置日志为警告级别,如果有数据是警告级别那么将记录到文件
5 scrapy
表单处理
5.1 目标地址
- 首页:http://www.cninfo.com.cn/new/commonUrl?url=disclosure/list/notice#regulator
- 接口:http://www.cninfo.com.cn/new/disclosure
5.2 程序编写
import scrapy
class PostTestSpider(scrapy.Spider):
name = 'post_test'
allowed_domains = ['cninfo.com']
# start_urls = ['http://www.cninfo.com.cn/new/disclosure']
def start_requests(self):
url = 'http://www.cninfo.com.cn/new/disclosure'
for i in range(1,5):
form_data = {
"column": "szse_gem_latest",
"pageNum": str(i),
"pageSize": "30",
"sortName": "",
"sortType": "",
"clusterFlag": "true"
}
yield scrapy.FormRequest(url=url,formdata=form_data,meta={'page':form_data['pageNum']})
def parse(self, response):
print(f'正在采集第{response.meta.get("page")}页')
6 框架扩展
6.1 框架去重设计
dont_filter
实现了框架去重的功能
import scrapy
import json
from scrapy import cmdline
class HuyaSpider(scrapy.Spider):
name = 'huya'
# allowed_domains = ['hy.com']
def start_requests(self):
url = ['https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=2',
'https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=2']
for i in url:
# 框架默认对地址进行了去重
yield scrapy.Request(url=i,dont_filter=False)
def parse(self, response):
items = json.loads(response.text)
data = items.get('data').get('datas')
print(len(data))
if __name__ == '__main__':
cmdline.execute('scrapy crawl huya'.split())
标签:框架,self,爬虫,Spider,Scrapy,com,class,def,scrapy 来源: https://www.cnblogs.com/feng0815/p/16691177.html