MOOC《Python网络爬虫和信息提取》(第11次)网络爬虫之框架(第4周)
MOOC–Python网络爬虫和信息提取(第11次开课)
网络爬虫之框架 21.08.10
目录
文章目录
测验4:Python网络爬虫之框架 (第4周)
1、下面哪个不是“网络爬虫与信息提取”相关的技术路线?
A、bs4-re
B、requests-bs4-re
C、requests-re
D、scrapy-bs4
正确答案 A
技术路线至少包含一个爬虫库和一个解析库,bs4和re都是解析库。
2、Requests库的方法与HTTP协议请求方法对应,下面哪个不是Requests库的对应方法?
A、.patch()
B、.get()
C、.put()
D、.push()
正确答案 D
3、判断一个网络爬虫应用可行性的最主要因素是什么?
A、部署代价和经济成本
B、网页条件,即尽量没有JavaScript脚本产生的数据
C、技术路线选取
D、Robots协议是否有允许
正确答案 D
Robots协议允许是爬虫能够实施的首要条件。
4、下面哪个不是网络爬虫可能引发的问题?
A、网络攻防对抗
B、性能骚扰
C、法律风险
D、隐私泄露
正确答案 A
爬虫不会造成网络攻防对抗,被爬取服务器可能会被爬虫攻击,但没有对抗。
5、以下不是Scrapy框架组成模块的是:
A、Blocklist
B、Downloader
C、Engine
D、Spiders
正确答案 A
Scrapy具有5+2结构,其中,5个模块分别是:Engine、Spiders、Scheduler、Downloader和Item
Pipelines。
6、在scrapy框架中,数据流最初始的请求来自于:
A、Downloader
B、Spiders
C、Engine
D、Scheduler
正确答案 B
Spiders模块给出了Scrapy爬虫最初始的请求
7、在Scrapy框架中,以下不是数据流所承载数据元素的是:
A、REQUESTS
B、ITEMS
C、URLS
D、RESPONSE
正确答案 C
Scrapy中使用REQUESTS表达URL,因此,URL不是其直接承载的元素。
8、在Scrapy框架中,请求从Spider模块发出后,被Engine发送到:
A、丢弃
B、Downloader
C、ITEM Pipeline
D、Scheduler
正确答案 D
Spider->Engine->Scheduler,注意,Spider请求不直接到Downloader模块。
9、在Scrapy框架中,Downloader爬取页面内容后,结果经Engine发送到哪个模块?
A、Scheduler
B、Spiders
C、丢弃
D、ITEM Pipelines
正确答案 B
Downloader->Engine->Spiders路径。
10、在Scrapy框架中,Spiders模块产生的HTML分析结果经Engine模块发送给哪个模块?
A、Downloader
B、Item Pipelines
C、Item Pipelines和Scheduler
D、Scheduler
正确答案 C
Spiders->Engine->(ITEMS) Item Pipelines
->(REQUESTS) Scheduler
根据不同类型的结果,有两个路径。
单元10:Scrapy爬虫框架
10.1 Scrapy爬虫框架介绍
Scrapy是快速功能强大的网络爬虫框架
-
爬虫框架是实现爬虫功能的一个软件结构和功能组件集合
-
爬虫框架是一个半成品,用户通过操作该模板,实现专业网络爬虫
10.1.1 Scrapy的安装
通用库的安装
**方法一:**通过Setting -> Project Interpreter -> Available Packages,该方法安装 Scrapy库 失败。
**安装方法二:**Terminal控制台安装,输入 pip install scrapy 下载安装(注意联网),安装后 输入 scrapy -h 测试。
10.1.2 Scrapy爬虫框架结构
“5+2”结构:
- ITEM PIPELINES(实体管道)
- SPIDERS(爬虫)
- ENGINE(引擎)
- SCHEDULER(调度器)
- DOWNLOADER(下载器)
- 2个MIDLEWARE(中间体)
数据流的路径:
Spider -> Engine -> Scheduler路径
1、Engine从Spider处获得爬取请求(Request)
2、Engine将爬取请求转发给Scheduler,用于调度
3、Engine从Scheduler处获得下一个要爬取的请求
Downloader->Engine->Spiders路径
4、Engine将爬取请求通过中间体发送给Downloader
5、爬取网页后,Downloader形成响应(Response)通过中间件发给Engine
6、Engine将收到的响应通过中间体发送给Spider处理
Spiders->Engine->(ITEMS) Item Pipelines及(REQUESTS) Scheduler路径
7、Spider处理响应后产生爬取项(scraped Item)和新的爬取请求(Requests)给Engine
8、Engine将爬取项发送给Item Pipeline(框架出口)
9、Engine将新的爬取请求发送给Scheduler
10.2 Scrapy爬虫框架解析
Engine
- 控制所有模块之间的数据流
- 根据条件触发事件
- 不需要用户修改
Downloader
- 根据请求下载网页
- 不需要用户修改
Scheduler
- 对所有爬取请求进行调度管理
- 不需要用户修改
Spider
- 解析Downloader返回的响应(Response)
- 产生新的爬取项(scraped item)
- 产生额外的爬取请求(Request)
- 需要用户编写配置代码
Item Pipelines
- 以流水线方式处理Spider产生的爬取项
- 由一组操作顺序组成,类似流水线,每个操作是一个Item Pipeline类型
- 可能操作包括:清理、检验和查重爬取项中的HTML数据、将数据存储到数据库
- 需要用户编写配置代码
Spider Middleware
- 目的:对请求和爬取项的再处理
- 功能:修改、丢弃、新增请求或爬取项
- 用户可以编写配置代码
10.3 request库和Scrapy爬虫的比较
相同点:
-
两者都可以进行页面请求和爬取,Python爬虫的两个重要技术路线;
-
两者可用性都好,文档丰富,入门简单;
-
两者都没有处理js、提交表单、应对验证码等功能(可扩展);
不同点:
Requests | Scrapy |
---|---|
页面级爬虫 | 网站级爬虫 |
功能库 | 框架 |
并发性考虑不足,性能较差 | 并发性较好,性能较高 |
重点在于页面下载 | 重点在于爬虫结构 |
定制灵活 | 一般定制灵活,深度定制困难 |
上手十分简单 | 入门稍难 |
应用的选择:
-
非常小的需求,requests库;
-
不太小的需求,Scrapy框架;
-
定制程度很高的需求(不考虑规模),自搭框架,requests > Scrapy
10.3 Scrapy爬虫的常用命令
命令 | 说明 | 格式 |
---|---|---|
startproject | 创建一个新工程 | scrapy startproject [ dir] |
genspider | 创建一个爬虫 | scrapy genspider [options] |
settings | 获得爬虫配置信息 | scrapy settings [options] |
crawl | 运行一个爬虫 | scrapy crawl |
list | 列出工程中所有爬虫 | scrapy list |
shell | 启动URL调试命令行 | scrapy shell [url] |
单元11:Scrapy爬虫基本使用
11.1 scary爬虫的第一个实例
产生步骤:
-
步骤1:建立一个Scrapy爬虫工程(文件夹 python123demo )
-
步骤2:在工程中产生一个Scrapy爬虫(demo.py)
-
步骤3:配置产生的spider爬虫(编写 parse方法)
-
步骤4:运行爬虫,获取网页。
# 相关命令行:
'''
1. 输入 scrapy startproject python123demo ,生成工程目录python123demo
2. 输入 scrapy genspider demo python123.io ,生成demo.py
3. 编写 parse 方法
4. 输入 scrapy crawl demo ,执行名为demo的爬虫
'''
# demo.py(简化版)
# 功能描述:
# 将 https://python123.io/ws/demo.html 的内容保存到demo.html文件中
import scrapy
class DemoSpider(scrapy.Spider): # 继承于scary.Spider类
name = 'demo' # 当前爬虫名字为 “demo”
# allowed_domains = ['python123.io'] # 域名
start_urls = ['http://python123.io/ws/demo.html'] # 爬取的链接
# parse 用于处理响应,对页面进行解析和操作的步骤
def parse(self, response):
fname = response.url.split('/')[-1] # 返回html文件的名字
with open(fname,'wb') as f: # 将网页内容保存到文件
f.write(response.body)
self.log('Saved file %s.' % name)
生成的目录工程内容详解:
11.2 yield关键字的使用
包含yield语句的函数是一个生成器,生成器每次通过 yield 产生一个值,函数就会被冻结,被唤醒时再产生一个值。
生成器的优势:
- 更节省存储空间(yield只占用一个数值的存储空间)
- 响应更迅速(每次调用即输出)
- 使用更灵活
# demo.py代码的完整版
import scrapy
class DemoSpider(scrapy.Spider):
name = 'demo'
def start_trquests(self):
urls = ['http://pyhton123.io']
for url in urls:
yield scrapy.Request(url = url, callback=self.parse)
def parse(self, response):
pass
11.3 scary爬虫的基本使用
使用步骤:
- 创建一个工程
- 编写Spider
- 编写Item Pipeline
- 优化配置策略
数据类型: Request类、Response类、Item类
Request类 class scrapy.http.Request( )
Request对象表示一个Http请求,由Spider生成,由Downloader执行
属性或方法 | 说明 |
---|---|
.url | Request对应的请求URL地址 |
.method | 对应的请求方法,'GET’‘POST’等 |
.headers | 字典类型风格的请求头 |
.body | 请求内容主体,字符串类型 |
.meta | 用户添加的扩展信息,在scrapy内部模块间传递信息使用 |
.copy() | 复制该请求 |
Response类 class scrapy.http.Response()
Response对象表示一个HTTP响应由Downloader生成,由Spider处理
属性或方法 | 说明 |
---|---|
.url | Response对应的URL地址 |
.status | HTTP状态码,默认是200 |
.headers | Response对应的头部信息 |
.body | Response对应的内容信息,字符串类型 |
.flags | 一组标记 |
.request | 产生Response类型对应的Request对象 |
.copy() | 复制该响应 |
Item类 class scrapy.item.Item()
ltem对象表示一个从HTML页面中提取的信息内容,由spider生成,由Item Pipeline处理Item类似字典类型,可以按照字典类型操作。
Scrapy支持的HTML信息提取方法
- Beautiful Soup
- lxml
- re
- Xpath Selector
- CSS Selector(常用)
单元12:实例4:股票数据Scrapy爬虫
该程序能够爬取股票名称,但结果仅有一个成功爬取结果,代码仍有待修改
# 股票数据爬虫(Scrapy)
'''
目标:获取上交所和深交所有股票的名称和交易信息
输出:保存到文件中
技术路线:scrapy
获取股票列表:
东方财富网:http://quote.eastmoney.com/stocklist.html
获取个股信息︰
百度股票:https://gupiao.baidu.com/stock/
单个股票:https://gupiao.baidu.com/stock/sz002439.htm1
富途牛牛:https://www.futunn.com/
单个股票:https://www.futunn.com/stock/688779-SH
步骤:
1. 建立工程和spider模板
2. 编写Spider
3. 编写Pipeline
4. 配置优化
'''
# --------------------------------------------------------------
# 步骤1:建立工程和Spider模板
# \>scrapy startproject TencentStocks
# \>cd TencentStocks
# \>scrapy genspider stocks TencentStock.io
# --------------------------------------------------------------
# 步骤2:编写spider
# stocks.py
import scrapy
import re
class StocksSpider(scrapy.Spider):
name = "stocks"
start_urls = ['http://quote.eastmoney.com/stock_list.html']
def parse(self, response):
for href in response.css('a::attr(href)').extract():
try:
stock = re.findall(r"[s][hz]\d{6}", href)[0]
url = 'http://gu.qq.com/' + stock + '/gp'
yield scrapy.Request(url, callback=self.parse_stock)
except:
continue
def parse_stock(self, response):
infoDict = {}
stockName = response.css('.title_bg')
stockInfo = response.css('.stock-bets')
name = stockName.css('.col-1-1').extract()[0]
code = stockName.css('.col-1-2').extract()[0]
info = stockInfo.css('li').extract()
for i in info[:13]:
key = re.findall('>.*?<', i)[1][1:-1]
key = key.replace('\u2003', '')
key = key.replace('\xa0', '')
try:
val = re.findall('>.*?<', i)[3][1:-1]
except:
val = '--'
infoDict[key] = val
infoDict.update({'股票名称': re.findall('>.*<', name)[0][1:-1] + \
re.findall('>.*<', code)[0][1:-1]})
yield infoDict
# --------------------------------------------------------------
# 步骤3:编写Item Pipelines
# pipelines.py
class TencentstocksPipeline:
def process_item(self, item, spider):
return item
class ScrapyGupiaoPipeline:
def open_spider(self, spider):
self.f = open('gupiao.txt', 'w')
def close_spider(self, spider):
self.f.close()
def process_item(self, item, spider):
try:
line = str(dict(item)) + '\n'
self.f.write(line)
except:
pass
return item
# # 修改settings.py部分内容,使能调用我们自定义的 ScrapyGupiaoPipeline类
ITEM_PIPELINES = {
'TencentStocks.pipelines.ScrapyGupiaoPipeline': 300,
}
# cmd执行 scrapy crawl stocks ,实现结果输出
配置的优化
settings.py
选项 | 说明 |
---|---|
CONCURRENT_REQUESTS | Downloader最大并发请求下载数量,默认32 |
CONCURRENT_ITEMS | Item Pipeline最大并发ITEM处理数量,默认100 |
CONCURRENT_REQUESTS_PER_DOMAIN | 每个目标域名最大的并发请求数量,默认8 |
CONCURRENT_REQUESTS_PER_IP | 每个目标IP最大的并发请求数量,默认0,非o有效 |
资料来源:
Python网络爬虫与信息提取_北京理工大学_中国大学MOOC(慕课) https://www.icourse163.org/course/BIT-1001870001