Scrapy_Dsprain
简介
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。我们只需要少量代码,就能够快速的抓取。
Scrapy使用了Twisted[‘twisted’]异步网络框架,可以加快我们的下载速度。
Scrapy的工作流程
模块 | 功能 | 实现方式 |
---|---|---|
Scrapy Engine(引擎) | 总指挥:负责数据和信号的在不同模块间传递 | scrapy框架实现 |
Scheduler (调度器) | 一个队列,存放引擎发过来的request请求 | scrapy框架实现 |
Downloader (下载器) | 下载引擎发送来的requests请求,并返回引擎 | scrapy框架实现 |
Spider (爬虫) | 处理引擎发来的response,提取数据,提取url,并交给引擎 | 需要手写 |
Item Pipeline (管道) | 处理引擎传过来的数据,比如存储 | 需要手写 |
Downloader Middlewares (下载器中间件) | 可以自定义的下载扩展中间件,比如设置代理 | 一般不用手写 |
Spider Middlewares (爬虫中间件) | 可以自定义request请求和进行response过滤 | 一般不用手写 |
Scrapy创建项目
# 安装scrapy
pip install Scrapy
# 创建项目
scrapy startproject projectname
# 创建爬虫
scrapy genspider spidername spider域名
# 提取数据,完善spider。
# 保存数据,pipeline中保存数据。
# 启动爬虫
scrapy crawl spidername
Scrapy项目目录结构
Scrapy编写爬虫
爬虫文件
创建爬虫之后,会在项目中spiders目录下生成爬虫名的py文件。我们要对这个文件进行完善。编写数据爬取方式。
itcast.py
import scrapy
class ItcastSpider(scrapy.Spider):
name = 'itcast' # 定义的爬虫名
allowed_domains = ['itcast.cn'] # 允许爬取的域名范围
start_urls = ['//www.itcast.cn/channel/teacher.shtml'] # 开始爬取的url
def parse(self, response):
# 数据解析方法。方法名不能修改。
li_list = response.xpath("//div[@class='tea_con']//li")
for li in li_list:
item = {}
item["name"] = li.xpath(".//h3/text()").extract_first()
item["title"] = li.xpath(".//h4/text()").extract()[0]
# extract_first() == extract()[0]
yield item
从考虑这其中提现空格符串:
extract() 返回一个包含有字符串数据的列表。extract_first() 返回列表的第一个字符串。同extract()[0]
注意力:
spider中的parse方法名不能修改。需要爬去的URL地址必须要属于allow_domain下的链接。start_urls 首次爬取的时候,可以不满足此条件。response.xpath()返回的是一个包含selector对象的列表。scrapy中的response没有content属性,使用body替代。response.body是二进制信息,使用时需要decode()转码。
spider的数据库传至pipline利用yield。让全部整个方程成为某个转换器,才能减少内存条占据。
爬虫构造请求
有很多之后,抓取都要从手机网页中分离出来出 URL,并抓取该URL中的主要内容。这之后就都要结构需求。class ItcastSpider(scrapy.Spider):
name = 'itcast' # 定义的爬虫名
allowed_domains = ['itcast.cn'] # 允许爬取的域名范围
start_urls = ['//www.itcast.cn/channel/teacher.shtml'] # 开始爬取的url
def parse(self, response):
next_url = response.xpath("").extract_first() # 获取到二级URL
# 构造请求
yield scrapy.Request(next_url, callback=self.parse2)
# 解析函数间传递数据。parse 传递数据到parse2
# item = {}
# .. 省略item中数据的获取过程。
# yield scrapy.Request(next_url, callback=self.parse2, meta={"item"=item})
def parse2(self, response):
# 对二级URL所做处理
pass
scrapy.Request 能构建一个requests,同时制定提取数据的callback函数。
scrapy.Request(url [, callback, method, headers, body, cookies, meta, dont_filter=False])
class ItcastSpider(scrapy.Spider):
name = 'itcast' # 定义的爬虫名
allowed_domains = ['itcast.cn'] # 允许爬取的域名范围
start_urls = ['//www.itcast.cn/channel/teacher.shtml'] # 开始爬取的url
def parse(self, response):
next_url = response.xpath("").extract_first() # 获取到二级URL
# 构造请求
# 解析函数间传递数据。parse 传递数据到parse2
item = {}
.. 省略item中数据的获取过程。
yield scrapy.Request(next_url, callback=self.parse2, meta={"item"=item})
def parse2(self, response):
# 对二级URL所做处理
item = response.meta["item"]
pass
dont_filter: 让scrapy的去重不会过滤当前url,scrapy默认有url去重的功能,对需要重复请求的url有重要用途。
pipeline
class MyspiderPipeline:
def open_spider(self, spider):
pass
def process_item(self, item, spider):
# 在这个方法中编写数据存储的方法。
return item
def close_spider(self, spider):
pass
完工pipeline编号后,需在settings中设定重置pipeline
ITEM_PIPELINES = {
'myspider.pipelines.MyspiderPipeline': 300,
# 'myspider.pipelines.MyspiderPipeline' pipeline的位置
# 300 权重。当有多个pipeline时,通过权重大小,决定执行顺序。
}
从settings中的pipeline布置就能够可以看出,pipeline就能够有多种。常见为了能让的两个作用:
可能会有多个spider,不同的pipeline处理不同的item内容。一个spider的内容可能要做不同的操作,比如存入不同的数据库。
特别注意:
pipeline的权重越小,优先级越高。pipeline中process_item方法名不能修改。
open_spider方法,不是默认生成的。这个方法从名字可以看出,是在开始爬虫之前调用的方法(既此方法运行在爬虫文件之前。)这个方法在整个爬虫过程中,只会执行一次。通过此方法,可以对spider对象预先添加属性信息,还可以进行连接数据库实例化,打开本地文件等操作。
closer_spider方法,在爬虫关闭的时候执行,仅执行一次。可以进行数据库关闭连接,关闭本地文件等结束操作。
items
为要提取的数据构建数据模型。
items.py
import scrapy
class MyspiderItem(scrapy.Item):
name = scrapy.Field()
.. 省略更多
在爬虫文件中,如果使用了items,则只能构建模型中定义的字段。如果模型中没有,会报错。
如果爬虫文件中成功使用了items获取数据,在pipeline.py文件中,item则为对应模型,可以通过下面方法进行判断。
from myspider.items import MyspiderItem
class MyspiderPipeline:
def process_item(self, item, spider):
if isinstance(item, MyspiderItem):
..
# 通过dict(item) 可以强转为dict字典类型。
return item
Log
在settings中,能设为在移动终端读取系统日志的Log游戏等级。在设为这一个指标,能全面禁止scrapy的载入和程序运行数据信息在移动终的读取。LOG_LEVEL = "WARNING"
在也许 现身系统异常的位置,加log输出电压。如蜘蛛文件夹目录,pipelines.py文件夹目录。
import logging
logger = logging.getLogger(__name__) # 这样处理之后,打印出的日志可以看到所在文件名
# 可能出现异常的地方
logger.warning("loginfo")
日志不在终端打印,保存本地的设置方法。
在settings中添加
LOG_LEVEL = "WARNING"
LOG_FILE = "./log.log"
settings
settings中的分配均有详细介绍的文档文件辅导,可自愿在采用时完成如何查看。BOT_NAME = 'myspider'
SPIDER_MODULES = ['myspider.spiders']
NEWSPIDER_MODULE = 'myspider.spiders'
LOG_LEVEL = "WARNING"
LOG_FILE = "./log.log"
# 设置user_agent。
USER_AGENT = ''
# Obey robots.txt rules 这个参数决定了爬虫是否遵循robots协议。
ROBOTSTXT_OBEY = True
# 设置最大并发请求数 (default: 16)
CONCURRENT_REQUESTS = 32
# Configure a delay for requests for the same website (default: 0)
# See //docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16
# 是否使用cookies,scrapy在请求二级url时,可以自动携带上级cookies (enabled by default)
#COOKIES_ENABLED = False
# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False
# 重写headers,注意user_agent,cookies 信息不能放入请求头,需要单独处理:
#DEFAULT_REQUEST_HEADERS = {
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# 'Accept-Language': 'en',
#}
# Enable or disable spider middlewares
# See //docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
# 'myspider.middlewares.MyspiderSpiderMiddleware': 543,
#}
# Enable or disable downloader middlewares
# See //docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
# 'myspider.middlewares.MyspiderDownloaderMiddleware': 543,
#}
# Enable or disable extensions
# See //docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
# 'scrapy.extensions.telnet.TelnetConsole': None,
#}
# Configure item pipelines
# See //docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'myspider.pipelines.MyspiderPipeline': 300,
}
# Enable and configure the AutoThrottle extension (disabled by default)
# See //docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False
# Enable and configure HTTP caching (disabled by default)
# See //docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
Scrapy CrawlSpider 使用
通常情况下,在爬取页面中的URL时,我们是根据xpath一个个获取,然后构造。
使用CrawlSpider可以让这个过程变得简单,让scrapy框架根据我们设定的规则,自动获取所需的URL。
# 创建爬虫命令
scrapy genspider -t crawl spidername spider域名
出现的网络爬虫程序
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class ChufaSpider(CrawlSpider):
name = 'chufa'
allowed_domains = ['cicr.gov.cn']
start_urls = ['//cicr.gov.cn/']
# 定义提取URL地址规则
# Rule是一个对象,在rules中实例化
# rules是一个元祖,可以实例化多个Rule
rules = (
# allow URL的正则。不需要主域名,会自动补充。
# LinkExtractor 连接提取器,提取URL地址
# callback 提取出来的URL地址的response会交给callback处理,根据业务判断是否需要此参数。
# follow 当前URL地址的响应是否重新经过rules来提取URL地址
Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
)
def parse_item(self, response):
item = {}
#item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
#item['name'] = response.xpath('//div[@id="name"]').get()
#item['description'] = response.xpath('//div[@id="description"]').get()
return item
重视:
CrawlSpider爬虫文件中,不能定义parse方法,parse有特殊功能。如果多个Rule都满足某一个URL,会从rules中选择第一个满足的进行操作。
LinkExtractor更好比较常见指标:
deny:满足括号中正则的URL一定不提取,优先级高于allow。allow_domains:会被提取的连接的domains。deny_domains:一定不会被提取连接的domains。restrict_xpaths:使用xpath表达式过滤连接。
spider.Rule更好熟悉运作:
process_links:指定某个函数。在获取到连接列表时将会调用该函数,主要用来过滤URL。process_request:指定某个函数。在该Rule提取到的每个requests时都会调用该函数,用来过滤requests。
Downloader Middlewares 下载中间件
当需要对请求和响应做自定义处理时,使用下载中间件。
Downloader Middlewares 默认的方法:
当每个request通过下载中间件时,该方法被调用。process_response(self, request,response,spider)
当下载器完成http请求,传递响应给引擎的时候调用。
class RandomUserAgentMiddleware:
def process_request(self, request, spider):
# 提前在settings中定义USER_AGENTS_LIST列表。
ua = random.choice(spider.settings.get("USER_AGENTS_LIST"))
request.headers["User-Agent"] = ua
request.meta["proxy"] = "协议+ip+端口" # 添加代理
def process_response(self, request, response, spider):
print(request.headers["User-Agent"]) # 查看每次使用的ua是否不同。
return response
中间的件界定,,须要在settings中祖册,同pipeline。
Scrapy 模拟登陆
再不用的scrapy,用的requests做爬虫技术时,仿真模拟登入有这三种工艺: 直接携带cookies请求页面。可以放到header中,也可以在requests中给到cookies参数。找接口发送POST请求,存储cookies。selenium.找到对应的input标签,输入信息点击登陆。 食用scarpy虚拟修改密码,也是都的多种形式: 直接携带cookies。不能放到请求头中,必须给到cookie找接口发送POST请求,scrapy默认会自动存储cookies(在settings中可以设置)。selenium把登录后的cookies保存到本地,scrapy发送请求前读取本地cookies。在开始使用scrapy模拟登陆之前,先要理解start_url的访问流程。首先,上面提到过,start_url在访问时,不会被allowed_domains规则所限制(这个限制是通过OffsiteMiddleware中间件实现的)。这是因为,我们在parse中构造的请求,是使用的scrapy.Request,而start_url的请求是使用的spider.start_requests 方法。通过源码可以看到具体实现内容。
理解了start_url的请求,就可以推测出,如果start_url是需要登录才能访问的,可以通过改写spider.start_requests 方法来实现登录后访问。
import scrapy
class ItcastSpider(scrapy.Spider):
name = '' # 定义的爬虫名
allowed_domains = [''] # 允许爬取的域名范围
start_urls = [''] # 开始爬取的url
def start_requests(self):
cookies = ""
# cookies转化为字典
cookies = {i.split("=")[0]:i.split("=")[1] for i in cookies.split("; ")}
yield scrapy.Request(
self.satrt_urls[0],
callback=self.parse,
cookies=cookies
)
def parse(self, response):
url = ''
# 默认情况下,scrapy在下次url请求时,可以自动携带cookies,不需要再次指定。
yield scrapy.Request(
url,
callback=self.parse_second
)
def parse_second(self, response):
pass
小技巧:可以在settings中设置 COOKIES_DEBUG=TRUE 参数,这样我们就可以在终端输出中看到cookie的传递,和cookie信息了。
Scrapy 模拟POST请求
实用scrapy.FormRequest方案。class ItcastSpider(scrapy.Spider):
name = '' # 定义的爬虫名
allowed_domains = [''] # 允许爬取的域名范围
start_urls = [''] # 开始爬取的url
def parse(self, response):
post_data = {}
.. 省略构造post_data
yield scrapy.FormRequest(
"url", # post请求路径
formdata=post_data,
callback=self.after_login
)
def after_login(self, response):
pass
后边此种工艺,需求不可避免找见POST提起位置。scrapy提拱了电脑自动获利Form表单控件上交位置路线的工艺。
class ItcastSpider(scrapy.Spider):
name = '' # 定义的爬虫名
allowed_domains = [''] # 允许爬取的域名范围
start_urls = [''] # 开始爬取的url
def parse(self, response):
yield scrapy.FormRequest.from_response(
response, # 自动的从response中寻找Form表单提交地址
formdata={"login":"..","password":".."}, # 需要输入表单的input名和要输入的值。scrapy自动填充后提交。
callback=self.after_login
)
def after_login(self, response):
pass
Scrapy shell
行在设备,对Scrapy能提供的性能指标通过运行和测验。以及测验xpath的最终、观察response蕴含的信息内容等方面。scrapy shell <url>
Scrapy Redis
scrapy_redis在scrapy的基础上实现了更多,更强大的功能。具体体现在:request去重,爬虫持久化,轻松实现分布式爬虫。
皇冠新体育APP相关的文章
- 公司里的VMware vSphere是用来干嘛的??? vSphere服务器架构简单讲解_太菜了怎么办?_vsphere架构
- 皇冠新体育APP:某医院基于超融合架构的规划设计和应用实践_米朵儿技术屋
- ECU的软硬件架构_汽车电子与软件开发
- 皇冠新体育APP:第三章 Flink基础理论之运行模式_随缘清风殇
- 皇冠新体育APP:FlinkSql解析复杂的JSON结构_酱紫很帅_flink json过滤
- 国内优秀的java开源saas项目分享_年少有为2025_java 开源saas系统
- 万字长文解析:分布式架构、SOA、微服务架构、API网关、ESB服务总线架构之间的关联及演进_senda66_esb企业总线和微服务
- 搭建Flink编程开发平台_何东旭..
- 皇冠新体育APP:Flink(Pometheus监控)_顶尖高手养成计划_prometheus监控flink集群
- 皇冠新体育APP:Flink??监控_京河小蚁_flink作业监控
- 皇冠新体育APP:一种子模块化的基于Hash刷新机制的iOS端数据驱动的MVVM架构思考_kicinio
- flink 运行方式和部署模式_矛始_flink运行
- flink中的时间属性_开飞机的杰西_flink 时间函数
- 皇冠新体育APP:flink checkpoint配置整理_路过君_P
- 4 年 Java 程序员十面阿里终拿下 offer,评级 P6+ 年薪 30-40w 无股票_90后小伙追梦之路_阿里p6+
- 皇冠新体育APP:Flink Catalog解读_杨林伟