Scrapy框架
Scrapy
不是一个简单的函数功能库;而是一个专业的网络爬虫框架
Scrapy 足以支持一般商业服务所需的爬虫能力:持续爬取、商业服务、高可靠性
scrapy库的安装:
pip install scrapy
scrapy -h
Available commands:
bench Run quick benchmark test
commands
fetch Fetch a URL using the Scrapy downloader
genspider Generate new spider using pre-defined templates
runspider Run a self-contained spider (without creating a project)
settings Get settings values
shell Interactive scraping console
startproject Create new project
version Print Scrapy version
view Open URL in browser, as seen by Scrapy
[ more ] More commands available when run from project directory
Unit1、Scrapy爬虫框架
一、Scrapy爬虫框架结构
- 爬虫框架
-
- 爬虫框架是实现爬虫功能的一个软件结构和功能组件集合。
- 是一个半成品,帮助实现专业网络爬虫。
- “5+2”结构: 已有实现,不用编写
-
-
- ENGINE 引擎
-
- 控制所有模块之间的数据流
- 根据条件触发事件
- SCHEDULER 调度器
-
- 对所有爬取请求进行调度管理,排访问顺序
- ITEM PIPELINES (出口) 用户编写(也叫配置),对提取的信息进行后处理
-
- 以流水线来处理Spider产生的爬取项
- 有一组操作顺序组成,类似流水线,每个操作是一个Item Pipeline类型
- 可能操作包括:清理、检验、查重爬取项的HTML数据、将数据储存到数据库
- SPIDERS (入口) 用户编写(也叫配置),提供初始URL链接,并解析所得网页内容,再提供链接
-
- 解析Downloader返回的响应(Response)
- 产生爬取项(scraped item)
- 产生额外的爬取请求(Request)
- DOWNLOADER 下载页面
- Downloader Middlewares (中间件)
-
- 目的:实施Engine、Scheduler、Downloader之间进行用户可配置的控制
- 功能:修改、丢弃、新增请求或响应(拦截)
- Spider Middleware (中间件)
-
- 目的:对请求和爬取项再处理
- 功能:修改、丢弃、新增请求或爬取项(拦截)
-
二、Requests vs. Scrapy
- 相同点:
-
- 都可进行页面请求和爬取,是Python爬虫的两个重要技术路线。
- 两都好用,文档丰富,入门简单。
- 都么有处理js、提交表单、应对验证码等功能(可扩展)
- 不同:
requests | Scrapy |
页面级 | 网站级 |
功能库 | 框架 |
并发性不足,性能差 | 并发性好,性能较强(基于异步结构设计,有时太快会被反爬虫发现) |
重点在于页面下载 | 重点在于爬虫框架 |
定制灵活 | 一般定制灵活,深度定制困难 |
上手十分简单 | 人门稍微难 |
三、Scrapy爬虫的常用命令
Scrapy命令行 (建立爬虫,运行爬虫)
Scrapy 是为持续运行设计的专业爬虫框架,提供操作的Scrapy命令行。
>scrapy <command> [options] [args]
命令行输入:
scrapy -h
常用命令:
startproject | 创建一个新工程 | scrapy startproject <name> [dir] |
genspider | 创建一个爬虫 | scrapy genspider [options] <name> <domain> |
settings | 获得爬虫配置信息 | scrapy settings [options] |
crawl | 运行一个爬虫 | scrapy crawl <spider> |
list | 列出工程中所有爬虫 | scrapy list |
shell | 启动URL调试命令行 | scrapy shell [url] |
Scrapy为什么采用命令行?
- 命令行(而不是图形界面)更容易自动化,适合脚本控制。
- 本质上,Scrapy是给程序员使用的,功能(而不是界面)更重要。
Unit2、Scrapy爬虫基本使用
产生步骤:
- 建立一个Scrapy爬虫工程
- 命令行:D:\pycode>scrapy startproject python123demo
-
- 生成工程目录:
-
- Python123demo/------>外层目录
-
- scrapy.cfg ------>部署Scrapy爬虫的配置文件,服务器
- Python123demo/-->Scrapy框架的用户自定义python代码
-
- __init__.py-->初始化脚本
- items.py -->Items代码模板(继承类)
- middlewares.py -->Middlewares代码模板(继承类)
- pipelines.py -->Pipelines代码模板(继承类)
- settings.py --->Scrapy爬虫的配置文件
- spiders/ ----->Spiders代码模板目录(继承类)
-
- __init__.py ----->初始文件,无需修改
- __pycache__/--->缓存目录,无需修改
- 在工程中产生一个Scrapy爬虫,产生一个Spider模板
- 命令行:D:\pycode>cd python123demo
-
- D:\pycode\python123demo>scrapy genspider demo python123.io #爬取域名
- Created spider 'demo' using template 'basic' in module: python123demo.spiders.demo作用:生成demo.py
- 编写产生的Spider模板
- 修改dome.py文件
- 运行爬虫,获取网页
start_urls = ['http://python123.io/ws/demo.html']
#等价方法,完整代码部分 :
def start_requests(self):
urls = [
'http://python123.io/ws/demo.html'
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)#当Url数量很大时,可以很有效的节省资源
yield关键字
yield <-->生成器
- 生成器:一个不断产生值的函数
- 包含yield语句的函数是一个生成器
- 生成器每次产生一个值(yield语句),函数被冻结,被唤醒后再产生一个值。
#生成器写法
def gen(n):
for i in range(n):
yield i**2
for i in gen(5):
print(i,' ', end="")
#普通写法
def square(n):
ls = [i**2 for i in range(n)]
return ls
for i in square(5):
print(i,' ', end="")
##当n=1M、10M、100M或更大?生成器的重要优势
为何要使用生成器?
- 生成器相比一次列出所有内容的优势
-
- 更节省储存空间
- 响应更迅速
- 使用更加灵活
Scrapy爬虫的使用步骤:
- 创建一个工程和Spider模板
- 编写Spider
- 编写Item Pipeline
- 优化配置策略
Scrapy爬虫的数据类型:
1、Request类 (class scrapy.http.Request())
- Request对象表示一个HTTP请求
- 由Spider生成,Downloader执行
属性、方法 | .url | .method | .headers | .body | .meta | .copy() |
说明 | 对应URL | 对应请求方法.'GET''POST' | 字典类型请求 头 头部自定义 | 字符串类型请求内容 | 用户添加的扩展信息,Scrapy内部传递信息 | 复制该请求 |
2、Response类 (class scrapy.http.Request())
- Request对象表示一个HTTP响应
- 由Downloader生成,Spider执行
属性和方法:
.url | .status | .headers | .body | .flags | .request | .copy(0 |
对应URL | HTTP状态码,默认200 | 头部 | 内容 | 一组标记 | 对应Request对象 | 复制该响应 |
3、Item类 (class scrapy.item.Item())
- Item对象表示一个从HTML页面中提取的信息内容。
- 由Spider生成,由Item Pipeline处理。
- Item类似字典类型,可以按照字典类型操作。
Scrapy爬虫提取信息的方法:
Beautiful Soup lxml re XPath Selector CSS Selector
Xpath Selector:
举例
##<div id="test1">大家好!</div>
data = response.xpath('//div[@id="test1"]/text()').extract()[0]
##<div id="test3">我左青龙,<span id="tiger">右白虎,<ul>上朱雀,<li>下玄武。</li></ul>老牛在当中,</span>龙头在胸口。<div>
data = response.xpath('//div[@id="test3"]')
info = data.xpath('string(.)').extract()[0]
CSS Selector的基本使用:(由W3C组织维护并规范)
<HTML>.css('a::attr(href)').extract()
a:标签名 href:标签属性
www.w3school.com.cn/cssref/css_selectors.asp (参考链接)
.class | .intro | 选择 class="intro" 的所有元素。 | 1 |
::selection | ::selection | 选择被用户选取的元素部分。 |
element | p | 选择所有 <p> 元素。 | 1 |
element,element | div,p | 选择所有 <div> 元素和所有 <p> 元素。 | 1 |
element element | div p | 选择 <div> 元素内部的所有 <p> 元素。 | 1 |
spider中应用举例:
start_urls = ["http://bj.lianjia.com/ershoufang/pg1tt2/"]
def parse(self, response):
# 获取当前页面的房屋列表
#house_lis = response.css('.house-lst .info-panel')
# 把结果输出到文件(在命令行中房屋标题会因为编码原因显示为乱码)
with open("homelink.log", "wb") as f:
## 使用css selector进行操作
#average_price = response.css('.secondcon.fl li:nth-child(1)').css('.botline a::text').extract_first()
#f.write("Average Price: " + str(average_price) + "\r\n")
#yesterday_count = response.css('.secondcon.fl li:last-child').css('.botline strong::text').extract_first()
#f.write("Yesterday Count: " + str(yesterday_count) + "\r\n")
#for house_li in house_lis:
# link = house_li.css('a::attr("href")').extract_first() # 获取房屋的链接地址
# title = house_li.css('a::text').extract_first() # 获取房屋的标题
# price = house_li.css('.price .num::text').extract_first() # 获取房屋的价格
Unit2、实例4,股票数据Scrapy爬虫
要求同实例3
Scrapy爬虫步骤:
- 创建一个工程和Spider模板
- scrapy startproject BaiduStocks
- cd BaiduStocks
- scrapy genspider stocks baidu.com
- 修改spiders/stocks.py文件
- 编写Spider
- 配置stocks.py文件
- 修改对返回页面的处理
- 修改对新增URL爬取请求的处理
- 编写Item Pipeline
- 配置pipelines.py文件
- 定义对爬取项(Scrapy Item)的处理类
- 配置Item_Pipelines选项(settings.py文件)
- 优化配置策略
- 配置并发连接选项(settings.py文件)
-
- CONCURRENT_REQUESTS Downloader最大并发请求下载数量,默认32
- CONCURRENT_ITEMS Item Pipeline最大并发ITEM处理数量,默认100
- CONCURRENT_REQUESTS_PER_DOMAIN 每个目标域名最大并发请求数量,默认8
- CONCURRENT_REQUESTS_PER_IP 每个目标IP最大并发请求数量,默认0,非0有效
- 执行程序
- scrapy crawl stocks
spider代码:
(stocks.py文件源代码)
# -*- coding: utf-8 -*-
import scrapy
import re
class StocksSpider(scrapy.Spider):
name = "stocks"
start_urls = ['http://quote.eastmoney.com/stocklist.html']
def parse(self, response):
for href in response.css('a::attr(href)').ectract():
try:
stock = re.findall(r'[s][hz]\d{6}', href)[0]
url = 'https://gupiao.baidu.com/stock/' + stock + '.html'
yield scrapy.Request(url, callback=self.parse_stock)
#此处callback 给出处理该Url 所对应的函数
except:
continue
def parse_stock(self, response):
infoDict = {}
stockInfo = response.css('.stock-bets')
name = stockInfo.css('.bets-name').extract()[0]
keyList = stockInfo.css('dt').extract()
valueList = stockInfo.css('dd').extract()
for i in range(len(keyList)):
key = re.findall(r'>.*</dt>', keyList[i])[0][1:-5]
try:
val = re.findall(r'\d+\.?.*</dd>', valueList[i])[0][0:-5]
except:
val = '--'
infoDict.update({'股票名称': re.findall('\s.*\(',name)[0].split()[0]+\
re.findall('\>.*\<', name)[0][1:-1]})
#使用yield,将结果封装成Item类,传给ItemPipeline
yield infoDict
pipelines.py文件源代码:
# -*- coding: utf-8 -*-
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
class BaidustocksPipeline(object):
def process_item(self, item, spider):
return item
class BaidustocksInfoPipeline(object):
#爬虫启动时Pipeline对应的方法
def open_spider(self, spider):
self.f = open('BaiduStockInfo.txt', 'w')
#爬虫关闭时Pipeline对应的方法
def close_spider(self, spider):
self.f.close()
#对每一个Item进行处理时对应的方法:主体函数
def process_item(self, item, spider):
try:
line = str(dict(item)) + '\n'
self.f.write(line)
except:
pass
return item
settings.py文件中被修改的区域:
- # Configure item pipelines
- # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
- ITEM_PIPELINES = {
- 'BaiduStocks.pipelines.BaidustocksInfoPipeline': 300,
- }
Unit3、扩展
表单提交、爬取周期、入库存储
requests-bs4-re
scrapy + PhantomJS
scrapyd-* https://pypi.python.org
Scrapy 爬虫的应用展望
- 普通价值:
-
- 基于Linux,7*24,稳定输出
- 商业级部署和应用(scrapyd-*)
- 千万规模内URL爬取、内容分析和存储
- 高阶价值:
-
- 基于docker,虚拟化部署
- 中间件扩展,增加调度和监控
- 各种反爬虫对抗技术
注: 可看慕课或b站上 嵩天老师讲的python网络爬虫与信息提取课程
本文为视频内容 转载自https://blog.youkuaiyun.com/youyinyou/article/details/77745507