sprider

爬虫在使用场景中的分类:
- 通用爬虫:
抓取系统重要组成部分,抓取的是一整张页面数据
- 聚焦爬虫:
是建立在通用爬虫的基础上,抓取的是页面中特定的局部内容
- 增量式爬虫:
检测网站中数据更新的情况,只会抓取网站中最新更新出来的数据

反爬机制
门户网站,可以通过指定相应的策略或者技术手段,防止爬虫程序进行网站数据的爬取。

http协议:
- 概念:服务器和客户端进行数据交互的一种形式
常用的请求头信息
User-Agent: 请求载体的身份标识
Connection: 请求完毕后,是断开连接还是保持连接
常用的响应头信息
Content-Type:服务器响应回客户端的数据类型

https协议:
安全的超文本传输协议(会进行数据加密)
加密方式
对称密钥加密
非对称密钥加密
证书密钥加密

requests模块:
urllib模块
requests模块:python中原生的一款基于网络请求的模块,
作用:模拟浏览器发送请求

 如何使用:
     - 指定url
	 - 发起请求
	 - 获取响应数据
	 - 持久化存储响应数据
	 
环境安装:
   pip install requests
实战:

数据解析:
正则
bs4
xpath(***)
聚焦爬虫:爬取页面中指定的页面内容

数据解析原理概述:

  • 解析的局部的文本内容都会在标签之间或者标签对应的属性中进行存储
  • 1.进行指定标签的定位
  • 2.标签或者标签对应的属性值中存储的数据值进行提取(解析)
    编码流程:
  • 指定url
  • 发起请求
  • 获取响应数据
  • 数据解析
  • 持久化存储

bs4进行数据解析:
- 数据解析的原理
1.标签定位
2.提取标签、标签属性中存储的数据值
bs4数据解析的原理:
1.实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中
2.通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取
环境安装:
pip install bs4
pip install lxml
如何实例化BeautifulSoup对象:
from bs4 import BeautifulSoup
对象的实例化:
1.将本地的html文档中的数据加载到该对象中
fp = open(’./安徽工业大学.html’,‘r’,encoding=‘utf-8’)
soup = BeautifulSoup(fp,‘lxml’)
2.将互联网上获取的页面源码加载到该对象中
page_text = response.text
soup = BeautifulSoup(page_text,‘lxml’)
提供的用于数据解析的方法和属性:
soup.tagName 返回的是html中第一次出现的tagName标签
find(‘tagName’): 等同于soup.div
属性定位:print(soup.find(‘div’,class/id/attr= ‘school200205’))
soup.find_all(‘tagName’): 返回符合要求=的所有标签(列表)
-select:
select(‘某种选择器(id,class,标签…选择器)’),返回的是一个列表
获取标签之间的文本数据:
soup.a.text/string/get_text()
text/get_text():可以获取某一个标签中的所有的文本内容
string:只能可以获取该标签下面直系的文本内容
获取标签中属性值:
soup.a[‘href’]
xpath解析:最常用且最便捷高效的一种解析方式,通用性
-xpath解析原理:
-1.实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中
-2.调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获
-环境的安装
- pip install lxml

  • 如何实例化一个etree对象: from lxml import etree
    • 1.将本地的html文档中的数据加载到该对象中
      etree.parse(filePath)
    • 2.可以将互联网上获取的源码数据加载到该对象中
      etree.HTML(‘page_text’)
    • xpath(‘xpath表达式’)
      /:表示的是从根节点开始做的定位,表示的是一个层级
      //:表示的是多个层级
      属性定位://div[@class=‘song’] tag[@attrName=‘attrValue’]
      索引定位://div[@class=‘song’]/p[3] 索引是从1开始的
      取文本:
      /text() 获取的是标签中直系的文本内容
      // text() 标签中非直系的文本内容(所有的文本内容)
      取属性:
      /@attrName ==>img/src

反爬机制:验证码:识别验证码图片中的数据,用于模拟登录操作
识别验证码的操作:
人工肉眼识别
第三方的自动识别: 全球鹰
使用流程:注册:普通和开发这两种模式
开发者用户的登录:创建一个软件->添加新软件->录入软件名称->提交(软件id和密钥)
下载示例代码:开发文档->点此下载:云打码接口DLL(选择语言python调用示例)
使用打码平台识别验证码的编码流程:
- 将验证码图片进行本地下载
- 调用平台提供的示例代码进行图片数据识别
模拟登录:
- 爬取基于某些用户的用户信息
需求:对人人网进行模拟的登录
- 点击登录按钮会发起一个post请求
- post请求中会携带登录之前录入的相关信息(用户名,密码,验证码。。。)
- 验证码:每次都会动态变化
http/https协议特性:无状态
没有请求到对应页面数据的原因:
发起的第二次基于个人主页页面请求的时候,服务器端并不知道该此请求是基于登录状态下的请求
cookie: 用于让服务器记录客户端的相关状态
-手动处理:通过抓包工具获取cookie值,将该值封装到headers中
-自动处理: cookie值的来源:模拟登录post请求后,有服务器端创建
session会话对象:作用:1.可以进行请求的发送
2.如果请求过程中产生了cookie,则该cookie会被自动的存储/携带在该session对象中
- 创建一个session对象:session = requests.Session()
- 使用seesion对象进行模拟登录post请求的发送(cookie就会被存储在session中)
- session对象对个人主页对应的get请求进行发送(携带了cookie)

代理:破解封IP的这种反爬机制
什么是代理:代理服务器
代理的作用:突破自身IP访问的限制,隐藏自身真实IP
代理相关网站:
快代理
西祠代理
www.goubanjia.com
代理ip的类型:
- http:应用到http协议对应的url中
- https: 应用到https协议对应的url中
代理ip的匿名度:
- 透明:服务器知道本次请求使用了代理,也知道了请求对应的真实ip
- 匿名:知道使用了代理,但是不知道真实的Ip
- 高匿:服务器不知道使用了代理,更不知道真实的ip

高性能异步爬虫:
目的:在爬虫中使用异步实现高性能的数据爬取操作
异步爬虫的方式:
-多线程,多进程:
好处:可以为相关阻塞的操作单独开启线程或者进程,阻塞操作就可以异步执行
缺点:无法无限制的开启多线程或者多进程

  • 线程池、进程池:
    好处:我们可以降低系统对进程或者线程创建和销毁的一个频率,从而很好的降低系统的开销
    缺点:池中线程或进程的数量是有上限的
    单线程+异步协程(推荐):
    event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件的时候,含就就会被循环执行
    coroutine:协程对象,我们可以将协程对象注册到事件循环中,它会被事件循环调用。我们可以使用async关键字来定义一个方法,这个方法在调用时
    不会被立即被执行,而是返回一个协程对象
    task:任务,它是对协程对象的进一步封装,包含了任务的各个状态
    future:代表了将来执行或还没有执行的任务,实际上和task没有本质区别
    async定义了一个协程
    await用来挂起阻塞方法的执行

selenium模块和爬虫的关联?
便捷的获取网站中动态加载的数据
便捷的实现模拟登录
什么是selenium模块?
基于浏览器自动化的一个模块
seleium使用流程:
环境安装:pip install selenium
下载一个浏览器的驱动程序
实例化一个浏览器对象
编写基于浏览器自动化的操作代码
执行js程序:execute_script(‘jsCode’)
selenium处理iframe(iframe页面的子标签)
如果定位的标签存在于iframe标签中,则必须使用switch_to.frame(id)
动作链(拖动):from selenium.webdriver import ActionChains
实例化一个动作链对象:action =ActionChains(bro)
action.click_and_hold(div):长按并点击操作
move_by_offset(x,y)
perform()让动作链执行
action.release() 释放动作链对象

12306模拟登录流程:
使用selenium打开登录页面
对当前selenium打开的这张页面进行截图
对当前图片的局部区域(验证码图片)进行截图
-好处:将验证码图片和模拟登录进行一一对应
使用超级鹰识别验证码图片(坐标)

scrapy框架:
什么是scrapy框架?
集成了很多功能并且具有很强通用性的一个项目模板
如何学习?
我们学习中专门学习框架封装的各种功能的详细用法
什么是scrapy?
爬虫中封装好的一个明星框架,功能:高性能的持久化存储,异步的数据下载,高性能的数据解析
分布式。
scrapy框架的基本使用:
环境的安装:
linux:pip install scrapy
window10:https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
-创建一个工程:scrapy startproject xxx
-cd xxx目录中
-在spiders子目录中创建一个爬虫文件
scrapy genspider spiderName www.xxx.com
-执行工程:
scrapy crawl spiderName
scrapy数据解析:
scrapy持久化存储:
基于终端指令:要求:只可以将parse方法的返回值存储到本地的文本文件中
注意:持久化存储的文本文件的类型只可以为: json、jl、csv、xml
指令:scrapy crawl xxx -o filePath
好处:简洁高效便捷
缺点:局限性很强(数据只能存储在指定后缀的文本文件中)
基于管道:
编码流程:
-数据解析
-在item中定义相关的属性
def parse(self, response):
div_list = response.xpath(’//*[@id=“content”]/div/div[2]/div’)
# 存储所有解析到的数据的列表
all_data = []
for div in div_list:
# xpath函数返回的为列表,列表中存放的数据为Selector类型的数据。
# 我们解析到的内容被封装在了Selector对象中,
# 需要调用extract()函数将解析的内容从Selecor中取出。
author = div.xpath(’./div[1]/a[2]/h2/text()’).extract_first()
content = div.xpath(’./a[1]/div[1]/span[1]//text()’).extract()
content = ‘’.join(content)
-将解析的数据封装存储在item类型的对象中
-将item类型的对象提交给管道进行持久化存储的操作
-在管道类的process_item中要将其接受到的item对象中存储的数据进行持久化操作
-在配置文件中开启管道
好处:通用性强
面试题:将爬取到的数据一份存储在本地,一份存储到数据库,如何实现?
管道文件中的一个管道类对应的是将数据存储带一种平台
爬虫文件提交的item只会给管道文件中第一个被执行的管道类接收
process_item中的return item表示将item传递给下一个即将被执行的管道类
基于Spider的全站数据爬取
全站数据的爬取:就是将网站中的某板块下的全部页码对应的页面数据进行爬取
需求:爬取校花网中的照片的名称
实现方式:将所有页面的url添加到start_ruls列表(不推荐)
自行手动进行请求发送(推荐):
手动请求发送:yield scrapy.Request(url,callback):callback专门用于数据解析的

五大核心组件:
Spider、下载器、调度器、管道、引擎
Spider->引擎->调度器->下载器->引擎->Spider->引擎->管道
调度器:过滤器、队列(请求对象去重,把请求对象加入到队列中)
管道:用于持久化存储的
spiders 引擎(Scrapy Engine)管道(item Pipeline)调度器(Scheduler)下载器(Downloader)

首先执行爬虫文件spider,spider的作用是
(1)解析(2)发请求,原始的url存储在于spider中
1:当spider执行的时候,首先对起始的url发送请求,将起始url封装成请求对象
2:将请求对象传递给引擎
3:引擎将请求对象传递给调度器(内部含有队列和过滤器两个机制),调度器将请求存储在队列(先进先出)中
4:调度器从队列中调度出url的相应对象再将请求传递给引擎
5:引擎将请求对象通过下载中间件发送给下载器
6:下载器拿到请求到互联网上去下载
7:互联网将下载好的数据封装到响应对象给到下载器
8:下载器将响应对象通过下载中间件发送给引擎
9:引擎将封装了数据的响应对象回传给spider类parse方法中的response对象
10:spider中的parse方法被调用,response就有了响应值
11:在spider的parse方法中进行解析代码的编写;
(1)会解析出另外一批url,(2)会解析出相关的文本数据
12: 将解析拿到的数据封装到item中
13:item将封装的文本数据提交给引擎
14:引擎将数据提交给管道进行持久化存储(一次完整的请求数据)
15:如果parder方法中解析到的另外一批url想继续提交可以继续手动进行发请求
16:spider将这批请求对象封装提交给引擎
17:引擎将这批请求对象发配给调度器
16:这批url通过调度器中过滤器过滤掉重复的url存储在调度器的队列中
17:调度器再将这批请求对象进行请求的调度发送给引擎

引擎作用:
1:处理流数据 2:触发事物
引擎根据相互的数据流做判断,根据拿到的流数据进行下一步组件中方法的调用

下载中间件: 位于引擎和下载器之间,可以拦截请求和响应对象;拦截到请求和响应对象后可以
篡改页面内容和请求和响应头信息。
爬虫中间件:位于spider和引擎之间,也可以拦截请求和响应对象,不常用。

-图片数据爬取之ImagesPipeline:
基于scrapy爬取字符串类型的书记和爬取图片类型的数据区别?
字符串:只需要基于xpath进行解析且提交管道进行持久化存储
图片:xpath解析出图片src的属性值,单独的对图片地址发起请求获取图片二进制类型的数据

ImagesPipeline:只需要img的src的属性值进行解析,提交到管道,管道就会对图片的src请求发送获取图片的二进制类型的数据,且还会帮我们进行持久化存储。

		需求:爬取站长素材中的高清图片
		使用流程:数据解析(解析出图片地址)
		          将存储图片地址的item提交到指定的管道类
				  在管道文件中自定制一个基于ImagesPipline的一个管道类
				     -get_media_request()
					 -file_path
					 -itrm_completed
				  在配置文件中:
				    指定图片存储的目录:IMAGES_STORE = './imgswangyijie'
					指定开启的管道:自定制的管道类 ITEM_PIPELINES = {
				'imgsPro.pipelines.ImgsproPipeline': 300,
					}

中间件:在引擎和下载器之间叫做下载中间件,在Spider和引擎中间的叫爬虫中间件
下载中间件:批量拦截到整个工程中的所有的请求和响应
拦截请求:UA伪装:process_request,
代理IP的设定:process_exception:return request
拦截响应:篡改响应数据
响应对象
需求:爬取网易新闻的评论数据(标题和对应的内容)
1.通过网易新闻中的首页解析出五大板块对应的详情页的url(没有动态加载)
2.没一个板块对应的新闻标题都是动态加载出来的(动态加载)
3.通过解析出每一条新闻详情页的url获取详情页的页面源码,解析出新闻内容。

CrawlSpider:类,Spider的一个子类
-全站数据爬取的方式
-基于Spider:手动请求发送

  • 基于CrawlSpider:全站数据的爬取
    -CrawlSpider的使用:
  • 创建一个工程:scrapy
  • cd xxx
  • 创建爬虫文件(CrawlSpider):
    -scrapy genspider -t crawl xxx www.xxxx.com
    -链接提取器:
    作用:在起始的url的中的链接中的需要的指定的链接进行提取(根据指定的规则进行(allow))
    -规则解析器:
    作用:将链接提取器提到的链接进行指定规则(callback)的解析

-分布式爬虫:
概念:搭建一个分布式的集群,让其对一组资源进行分布联合的爬取
作用:提升爬取数据的效率
如何实现分布式?
-安装一个scrapy-redis的组件
-原生的scrapy是不能实现分布式爬虫?必须要让scrap结合着scrapy-redis组件实现分布式爬虫
调度器不可以被分布式集群共享
管道不可以被分布式集群共享
scrapy-redis组件的作用:可以给原生的scrapy框架提供可以被共享的管道和调度器
实现流程:
-创建一个工程
-创建一个CrawlSpider的爬虫文件
-修改当前的爬虫文件:
导入from scrapy_redis.spiders import RedisCrawlSpider
将start_urls和allowed_domains进行注释掉
添加一个新的属性:redis_key = 'sun’可以被共享的调度器队列的名称
修改配置文件settings:
指定使用可以被共享的管道:
ITEM_PIPELINES = {
‘scrapy_redis.pipelines.RedisPipeline’: 300
}
指定调度器:
###### (必须)使用 Scrapy-Redis 的调度器,在 Redis 中分配请求
SCHEDULER = “scrapy_redis.scheduler.Scheduler”

	###### (必须)使用 Scrapy-Redis 的去重组件,在 Redis 数据库中做去重
	DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

	###### (必须)允许爬虫出现暂停和暂停后恢复,也就是说不清理 Redis 队列
	SCHEDULER_PERSIST = True
redis相关操作配置:
    配置redis的配置文件:redis.conf
	打开配置文件,修改两个地方 bind 127.0.0.1 --> #bind 127.0.0.1
	          关闭保护模式 protected-mode yes改为no
	结合着redis开启服务:redis-server /etc/redis.conf 
	查看是否启动成功:cd /user/local/bin
	                  ps -ef | grep redis
    启动客户端:redis-cli 
-执行工程:scrapy runspider xxx.py
-向调度器的队列中放入一个起始的url: 
    调度器的队列在redis的客户端中
	  lpush xxx www.xxx.com
指定redis服务器:
    #指定redis服务:
    REDIS_HOST = '10.35.2.24' # redis远程服务器的ip()

	###### (必须)指定连接 Redis 数据库端口号
	REDIS_PORT = 6379
爬取的数据存储在redis的proName:items这个数据结构中

增量式爬虫:
概念:检测网站数据更新的情况,只会爬取网站最新更新出来的数据

反爬虫机制:
1.网站需要登录,登录-验证码
2.Ip限制
3.数据屏蔽–js数据加密 微博(ajax的异步数据获取),今日头条

上一篇:爬虫部署,服务端安装使用scrapyd,客户端安装scrapy-client,利用scrapy-client 发布爬虫到远程服务端


下一篇:Gerrit日常维护记录