爬虫基础知识笔记
爬虫
1.1 爬虫概念
-通过编写程序,模拟浏览器上网,然后让其去互联网上抓取数据的过程
爬虫价值
-实际应用
-就业
1.2 爬虫的合法性探究
1.3爬虫在使用场景中的分类
- 通用爬虫
抓取系统重要组成部分,抓取的是一整张页面数据
- 聚焦爬虫
建立在通用爬虫基础上,抓取局部内容
- 增量式爬虫
检测网站中数据更新的情况,只会抓取网站中最新更新出来的数据
爬虫的矛与盾
反爬机制
门户网站,可以通过制定相应的策略或者技术手段,防止爬虫程序
反反爬策略
爬虫程序也可制定相关策略或者技术手段,破解门户网站中具备的反爬策略
robots.txt协议
君子协议,规定网站中那些数据可以爬取哪些不可以爬取的数据
http协议
-概念:就是服务器和客户端进行数据交互的一种形式
常用请求头信息
- user-agent : 请求载体的身份标识
- Connection: 请求完毕后,是断开连接还是保持连接
常用响应头信息
- Content-Type: 服务器响应回客户端的数据类型
https 协议:
- 安全的超文本传输协议
加密方式
-对称密钥加密
-非对称密钥加密
-证书密钥加密
第二章
-urllib模块
--request 模块
2.1 request 模块:python中原生的一款基于网络请求的模块
作用:模拟浏览器发请求
如何使用:(request模块的编码流程)
- 指定url
-UA伪装
-请求参数的处理
- 发起请求
- 获取响应数据
- 持久化存储
环境的安装:
pip install requests
实战编码:
- 需求:爬取搜狗首页的页面数据
实战巩固:
需求:爬取搜狗指定词条对应的搜索结果页面(简易网页采集器)
-UA 检测
-UA 伪装
需求:破解百度翻译
- post请求(携带了参数)
- 响应数据是一组json数据
需求:爬取豆瓣电影分类排行榜 http://movie.douban.com/中的电影详情数据
需求:爬取肯德基餐厅查询 http://www.kfc.cn/kfccda/index.aspx中指定地点的餐厅数
需求:爬取国家药品监督管理局中基于中华人民共和国化妆品生产许可证相关数据
http://125.35.6.84:81/xk/
- 动态加载数据
- 首页中对应的企业信息数据是通过ajax动态请求到的
http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp?id=ff83aff95c5541cdab5ca6e847514f88
http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp?id=67a09a7960794de9a3821a896967f9b7
- 通过对详情页的url的观察发现:
url的域名都是一样的,只有携带的(id)不一样
ID值可以从首页对应的ajax请求到的json串中获取
域名和id值拼接处一个完整的企业对应的详情页的url
- 详情页的中的企业数据也是动态加载出来的
- 观察后发现:
- 所有post请求的url是一样的,只是id不同
- 如果我们可以批量获取多家企业家的id后,就可与url形成一个完整的详情页面对应详情数据
第三章 数据解析
聚焦爬虫:
正则
bs4
xpath
聚焦爬虫:爬出页面中指定的内容。
编码流程:
1 制定url
2 发起请求
3 获取响应数据
4 数据解析
5 持久化存储
数据解析分类:
- 正则
- bs4
- xpath ***
数据解析原理概述:
- 解析的局部的文本都会在文本之间或者标签对应的属性中进行存储
1 进行制定标签的定位
2 标签或者标签对应的属性中存储的数据进行提取(解析)
正则解析:
<dd class="content content-pic">
<img src="/Uploads/joke/2020/02/25/5e548f062756c.jpg" alt="欠债还钱天经地义" val="/Uploads/joke/2020/02/25/5e548f062756c.jpg"> </dd>
<dd class="content content-pic">
<p><img src="/Uploads/joke/2020/02/23/5e52815d076a7.jpg" alt="我知道过10的机会来了" val="/Uploads/joke/2020/02/23/5e52815d076a7.jpg"></p> </dd>
ex ='<dd class="content content-pic">.*?<img src="(.*?)" alt.*?</dd>'
bs4进行数据解析:(适用于python)
-数据解析原理:
1标签定位
1提取标签,标签属性中存储的数据值
- bs4数据解析原理
-1 实例化一个beautifulsoup对象,并且将页面数据加载到该对象中
-2 通过调用beautifulsoup对象中相关属性或者方法进行标签定位和数据提取
- 环境安装:
-pip install bs4
-pip install lxml(解析器)
- 如何实例化beautifulsoup对象:
-from bs4 import BeautifulSoup
- 将对象实例化
1 将本地的html文档中的数据加载到该对象中
fp = open('./text.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml') #将本地的html文档中的数据加载到该对象中
2 将互联网上获取的页面加载到该对象中
page_text = response.text
soup = BeautifulSoup(page_text,'lxml')
3 提供的用于数据解析的属性和方法
--soup.tagName: 返回的是html文件第一次出现的tagname对应的标签
--soup.find():
- soup.find('div') : 等同于soup.div
- 属性定位
soup.find('div',class_/id/attr = 'song') #注意"_"
--soup.find_all('tagname') :返回符合要求的所有标签(列表)
--soup.select():
-select('某种选择器(id,class,标签...选择器)')返回的是一个列表 例如:soup.select(".hzbtabs")
-层级选择器
-soup.select('.tang' > ul >li >a'): > 表示的一个层级
-soup.select('.tang' > ul a'): 空格 表示的是多个层级
- 获取标签之间的文本数据:
- soup.a.text/string/get_text()
区别:text/get_text() 可以获取某一便签下的所有文本内容
sting只能获取标签下面直系的文本内容
- 获取标签中的属性值:
- soup.a['href'] (href 指的是url)
例如:print(soup.select('.hzbbannertxt >a')[0]['href'])
xpath解析 :
最常用的且最便捷高效的一种解析方式,通用性。
- xpath解析原理:
-1 实例化一个etree的对象,且需要将被解析的页面源数据加载到该对象中
-2 调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获
-环境的安装:
- pip install lxml
- 如何实例化一个etree对象: from lxml import etree
- 1 将本地的html文档中的源码数据加载到etree对象中
etree.parse(filepath)
- 2 可以将从互联网上获取的源码数据加载到该对象中
etree.HTML('page_tree')
- xpath('xpath表达式')
-xpath表达式
- / :表示的是从根节点开始定位,表示的是一个层级
- //:表示的是多个层级。可以表示从任意位置定位
- 属性定位 ://div[@class = 'song'] # tag[attrname='attrvalue']
- 索引定位 ://div[@class = 'song'] # 索引从1开始
- 取文本
- /text() 获取的是标签中直系的文本内容
- //text() 获取的是标签中非直系的文本内容(所有文本内容)
- 取属性
/@attrname ==>>>img/@src
小知识 :# 通用处理中文乱码的解析方式
img_name = img_name.encode('iso-8859-1').decode('gbk')
第三章 验证码识别
反爬机制:验证码 识别验证码图片数据,用于模拟登陆操作
识别验证码
- 人工肉眼识别(不推荐)
- 第三方自动识别(推荐)
云打码 http://www.yundama.com/price.html
云打码使用流程:
- 注册 :普通和开发者用户
- 登陆
- 普通用户的登陆:查询题分
- 开发者用户的登陆:(bobo328410948)
-创建一个软件: 我的软件--》添加新软件--》录入软件名称--》提交(软件id和密钥)
-下载示例代码:开发文档》点击下载:云打码接口DLL》PYTHONHTTP示例下载
实战 :识别古诗文网登陆页面中的验证码
- 将验证码图片进行本地下载
- 使用平台提供的示例代码进行图片数据识别
第四章 requests模块高级操作
- 模拟登陆
- 爬去基于某些用户的用户信息
需求: 对人人网进行模拟登陆
- 点击登陆按钮之后会发起一个post请求
- post请求中会携带登陆之前录入的相关的登陆信息(用户名,密码,验证码...)
- 验证码:每次请求都会变化
需求:
爬取当前用户的相关用户信息 (个人主页中显示的信息)
http/https协议特性:无状态
没有请求到对应页面数据的原因:
发起的第二次基于个人主页页面请求的时候,服务器端并不知道此请求是基于登陆状态下的请求
cookie: 用来让服务器端记录客户端的相关状态
- 手动处理:通过抓包工具获取cookie值,将该值封装到headers中
- 自动处理:
cookie值的来源是哪里?
- 模拟登陆post请求后,由服务器端创建
session会话对象:
-作用:
1可以进行请求的发送
2如果请求过程中产生了cookie,则该cookie会被自动存储/携带在该session对象中
- 创建session对象(session = requests.Session())
- 使用session对象进行模拟登陆post请求的发送(cookie就就会存储在session中)
- session对象对个人主页对应的get请求进行发送(携带了cookie)
代理:破解封IP这种反爬机制
什么是代理:
- 代理服务器.
代理的作用:
- 突破自身IP访问的限制
- 隐藏自身真实的IP
代理相关的网站:
- 快代理
- 西祠代理
- www.gouban.com
?第六章 高性能异步爬虫
目的:在爬虫中使用异步实现高性能的数据爬取
异步爬虫的方式:
- 多线程,多进程:(不建议)
好处:可以为相关阻塞的操作单独开启线程或者进程,阻塞就可以异步执行
弊端: 无法无限制的开启多线程或者多进程。
- 线程池,进程池(适当的使用):
好处:我们可以降低系统对进程或者线程创建和销毁的一个频率,从而很好的降低系统的开销
弊端:池中线程或进程的数量是有上限。
-3.单线程+异步协程(推荐)
?第七章 selenium模块的基本使用
问题:selenium模块和爬虫之间具有怎样的关联?
- 便捷的获取网站中动态加载的数据
- 便捷实现模拟登陆
什么是selenium模块?
- 基于浏览器自动化的一个模块
selenium使用流程:
- 环境的安装: pip install selenium
- 下载一个浏览器的驱动程序(谷歌浏览器)
- 下载路径 http://chromedriver.storage.googleapis.com/index.html
- 驱动程序和浏览器的映射关系:https://blog.csdn.net/whale_and/article/details/82455126
- 实例化一个浏览器对象
- 编写基于浏览器自动化的操作代码
- 发起请求:get(url)
- 标签定位:find系列的方法
- 标签交互:send_keys('xxx')
- 执行js程序:excute_script('jsCode')
- 前进,后退:back(),forward()
- 关闭浏览器:quit()
- selenium处理iframe+动作链
- 如果定位的标签存在于iframe标签之中,则必须使用switch_to.frame(id)
- 动作链(拖动):from selenium.webdriver import ActionChains
- 实例化一个动作链对象:action = ActionChains(bro)
- click_and_hold(div):长按且点击操作
- move_by_offset(x,y)
- perform()让动作链立即执行
- actoni.release()释放动作链对象
第八章 scrapy框架
8.1 scrapy框架初识
- 什么是框架?
- 就是一个集成了很多功能并且具有很强通用性的一个项目模板。
- 如何学习框架?
- 专门学习框架封装的各种功能的详细用法。
- 什么是scrapy?
- 爬虫中封装好的一个明星框架。功能:高性能的持久化存储,异步的数据下载,高性能的数据分析,分布
- Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍。
8.2 scrapy 环境安装
- 环境安装:
linux和mac操作系统:
pip install scrapy
- windows系统:
pip install wheel
下载twisted,下载地址为http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
安装twisted:pip install Twisted‑17.1.0‑cp36‑cp36m‑win_amd64.whl
pip install pywin32
pip install scrapy
测试:在终端里录入scrapy指令,没有报错即表示安装成功!
8.3 scrapy 基本使用
- 创建一个工程:scrapy startproject xxxpro
- cd xxxpro
- 在spiders子目录中创建一个爬虫文件
- scrapy genspider spiderName www.xxx.com
- 执行工程:
- scrapy crawl siderName
- setting:
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
# 显示指定类型的日志信息
LOG_LEVEL = 'ERROR'
(小知识:'cls'用于清屏)
8.4 scrapy 数据解析
# 列表转为字符串
str = ''.join(list)
#xpath返回的是列表,但是列表元素一定是Selector类型对象
# extract可以将Selector对象中data参数存储的字符串提取出来
response.xpath('//div[@class = "main-left fl"]/dl')
user = dl.xpath('./dt/p/a[1]/text()')[0].extract()
# 列表调用了extract之后,则表示将列表中每一个Selector对象中data对应的字符串提取出来
content = dl.xpath('./dt/span/a/text()').extract_first()
- scrapy持久化存储
- 基于终端指令
- 要求 :只可以将parse方法的返回值存储到本地的文本文件中
- 注意 : 持久化存储对应的文本文件的类型只可以为:
- 指令 : scrapy crawl xxx -o filepath
- 好处 : 简洁高效便捷
- 缺点 : 局限性比较强(数据只可以存储到指定后缀的文本文件中),
('json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle')
- 基于管道:
- 编码流程:
- 数据解析
- 在item类中定义相关属性
- 将解析的数据封装到item类型的对象中
- 将item类型的对象提交给管道进行持久化存储的操作
- 在管道类的process_item中要将其接受到的item对象中存储的数据进行持久化存储
- 在配置文件中开启管道
- 好处:
- 通用性强
- 面试题: 将爬取的数据一份存储到本地一份存储到数据库,如何实现?
?8.7
8.8 基于spider的全站数据爬取
- 就是将网站中某板块下的全部页面对应的页面数据进行爬取
- 需求:爬取校花网中的图片的名称
- 实现方式:
- 将所有页面的url添加到start_urls列表(不推荐)
- 自行手动的进行请求发送:
- yield scrapy.Request(url,callback):callback专门用作于数据解析的
8.9 五大核心组件
- 引擎(Scrapy)
用来处理整个系统的数据流处理, 触发事务(框架核心)
- 调度器(Scheduler)
用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
- 下载器(Downloader)
用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
- 爬虫(Spiders)
爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
- 项目管道(Pipeline)
负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
8.10 请求传参
- 使用场景:如果爬取解析的数据不再同一张页面中。(深度爬取)
- 爬取boss的岗位名称,岗位描述
8.12
- 图片数据爬取之imagesPipeline
- 基于scrapy爬取字符串类型的数据和爬取图片类型的数据区别?
- 字符串:只需要基于xpath进行解析且提交管道进行持久化存储
- 图片 :xpath解析出图片src的属性值。单独的对图片地址发起请求获取图片二进制类型的数据
- ImagesPineline:(from scrapy.pipelines.images import ImagesPipeline)
- 只需要将img的属性值进行解析,提交到管道,管道就会对图片的src进行请求发送获取图片的二进制类型的数据
且还会帮我们存储
- 需求: 爬取站长素材中的高清图片
- 使用流程:
- 数据解析(图片的地址)
- 将存储图片地址的item提交到指定的管道类
- 在管道文件中自制一个基于ImagesPipiline的一个管道类
- get_media_request()
- file_path()
- item_completed
- 在配置文件中:
- 指定图片存储的目录: IMAGES_STORE = './imgs_bobo'
- 指定开启的管道:自定制的管道类
8.14 中间件初始
- 下载中间件
- 位置:引擎和下载器之间
- 作用: 批量拦截到整个工程中所有的请求和响应
- 拦截请求:
- UA伪装 process_request
- 代理IP process_exception: return request
- 拦截响应:
- 篡改响应数据,响应对象
小知识: ( ctrl + c 强制中断 终端)
- 需求:爬取网易新闻中的新闻数据(标题和内容)
- 1 通过网易新闻的首页解析出五大板块对应的详情页的url(没有动态加载)
- 2 每一个板块对应的新闻标题都是动态加载出来的(动态加载)
- 3 通过解析出每一条新闻详情页的url获取详情页的页面数据,解析出新闻内容
8.15 CrawlSpider:类,Spider的一个子类
- 全站数据爬取的方式
- 基于Spider: 手动请求
- 基于CrawlSpider
- CrawlSpider的使用:
- 创建一个工程
- cd XXX
- 创建爬虫文件(CrawlSpider)
- scrapy genspider -t crawl xxx www.com
- 链接提取器:
- 作用:根据指定的规则(allow)进行指定链接的提取
- 规则解析器:将链接提取器提取到的链接进行指定规则(callback)的解析操作
需求:爬取sun网站中的编号,新闻标题,新闻内容,标号
- 分析:爬取的数据没有在同一张页面中
- 1.可以使用链接提取器提取所有页码的链接
- 2.让链接提取器提取所有新闻详情页的链接
8.16 分布式爬虫
- 概念:我们需要搭建一个分布式的集群,让其对一组资源进行分布联合爬取
- 作用:提升爬取数据的效率
- 如何实现分布式?
- 安装一个scrapy-redis的组件
- 原生的scrapy是不可以实现分布式爬虫,必须让scrapy结合着scrapy_redic组件一起实现分布式爬虫
- 为什么原生的scrapy不可以实现分布式爬虫?
- 调度器不可以被分布式机群共享
- 管道不可以被分布式机群共享
- scrapy-redis组建作用:
- 可以给原生的scrapy框架提供可以被共享的管道和调度器
- 实现流程:
- 创建一个工程
- 创建一个基于CrawlSpider的爬虫文件
- 修改当前的爬虫文件:
- 导包:from scrapy_redis.spiders import RedisCrawlSpider
- 将start_urls和allowed_domains进行注释
- 添加一个新属性:redis_key = 'sun'可以被共享的调度器队列的名称
- 编写数据解析相关的操作
- 将当前爬虫的父类修改为RedisCrawlSpider
- 修改配置文件settings
- 指定使用可以被共享的管道:
#指定管道
ITEM_PIPELINES = {'scrapy_redis.pipelines.RedisPipeline':400}
- 指定调度器
# 增加了一个去重容器类的配置, 作用使用Redis的set集合来存储请求的指纹数据, 从而实现请求去重的持久化
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis组件自己的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 配置调度器是否要持久化, 也就是当爬虫结束了, 要不要清空Redis中请求队列和去重指纹的set。如果是True, 就表示要持久化存储, 就不清空数据, 否则清空数据
SCHEDULER_PERSIST = True
- 指定redis服务器
#指定redis
REDIS_HOST = '127.0.0.1' #redis远程服务器的ip(修改)
REDIS_PORT = 6379
- redis相关操作配置
- 配置redis的配置文件:
- linux或者mac:redis.conf
- windows:redis.windows.conf
- 代开配置文件修改
- 将bind 127.0.0.1进行删除
- 关闭保护模式:protected_mode yse改为no
- 结合着配置文件开启redis服务
- redis-server 配置文件
- 启动客户端:
- redis-cli
- 执行工程:
- scrapy runspider xxx.py
- 向调度器的队列中放入一个起始的url:
- 调度器的队列在redis的客户端中
- lpush xxx www.xxx.com
- 爬取到的数据存储在了redis的proName:items这个数据结构中
8.17 增量式爬虫
- 概念:检测网站数据更新的情况,只会爬取网站最新更新出来的数据。
- 分析:
- 指定一个起始的url
- 基于CrawlSpider获取其他页码链接
- 基于Rule将其他页码链接进行请求
- 从每一个页码对应的页面源码数解析出每一部电影详情页的URL
- 检测电影详情页的url之前有没有请求过
- 将爬取过的电影详情页的url存储
- 存储到redis的set数据结构(可以自动去重)
- 对详情页的url发起请求,然后解析出电影的名称和简介
- 进行持久化存储
作者:华王
博客:https://www.cnblogs.com/huahuawang/