爬虫入门笔记

爬虫

数据的由来

数据如果想要发挥它的作用,必须要分析。

爬虫最重要的作用就是获取数据。

爬虫的定义

(1)定义:爬虫就是自动抓取互联网信息的脚本或者程序。

(2)爬虫可以解决的问题。

​ a、解决冷启动问题。

​ b、搜索引擎的根基:做搜索引擎少不了爬虫。

​ c、建立知识图谱,帮助建立机器学习知识图谱。【数据集】—>[训练集]+测试集

jquery是什么?

​ document.gete

​ 选择器可以快速写代码。—使得js编程更加简单。

建议:大家找本书去读一读。因为做网页和爬虫js都非常重要。

(3)爬虫工程师的进阶之路

​ 初级爬虫工程师

​ 1.web 前端的知识: HTML、CSS、JavaSc1ipt、 DOM、 DHTML 、Ajax、jQuery、json 等;

​ 2、正则表达式, 能提取正常一般网页中想要的信息,比如某些特殊的文字, 链接信息, 知道什么是懒惰, 什么是贪婪型的正则;

​ 3、会使用 XPath 等获取一些DOM 结构中的节点信息;

​ 4、知道什么是深度优先, 广度优先的抓取算法, 及实践中的使用规则;

​ 5、能分析简单网站的结构, 会使用urllib或requests 库进行简单的数据抓取。

​ 中级爬虫工程师:

​ 1、了解什么事HASH,会简单地使用MD5,SHA1等算法对数据进行HASH一遍存储

​ 2、熟悉HTTP,HTTPS协议的基础知识,了解GET,POST方法,了解HTTP头中的信息,包括返回状态码,编码,user-agent,cookie,session等。

​ 3、能设置user-agent进行数据爬取,设置代理等。

​ 4、知道什么事Request,什么事response,会使用Fiddler等工具抓取及分析简单地网络数据包;对于动态爬虫,要学会分析ajax请求,模拟制造post数据包请求,抓取客户端session等信息,对于一些简单的网站,能够通过模拟数据包进行自动登录。

​ 5、对于一些难搞定的网站学会使用phantomjs+selenium抓取一些动态网页信息

​ 6、并发下载,通过并行下载加速数据爬取;多线程的使用。

​ 高级爬虫工程师:

​ 1、能够使用Tesseract,百度AI,HOG+SVM,CNN等库进行验证码识别。

​ 2、能使用数据挖掘技术,分类算法等避免死链。

​ 3、会使用常用的数据库进行数据存储,查询。比如mongoDB,redis;学习如何通过缓存避免重复下载的问题。

​ 4、能使用一些开源框架scrapy,scrapy-redis等分布式爬虫,能部署掌控分布式爬虫进行大规模数据爬取。

爬虫的分类

爬虫可以分为通用爬虫和聚焦爬虫。

1、通用爬虫:就是将互联网上的数据整体爬取下来保存到本地的一个爬虫程序,是搜索引擎的重要组成部分。

(1)搜索引擎:就是运用特定的算法和策略,从互联网上获取页面信息,并将信息保存到本地为用户提供检索服务的系统。

(2)搜索引擎的工作步骤:

​ 第一步:抓取网页

​ 涉及到一个问题,如果获取页面的Url,使得搜索引擎涉及到所有的网页。—>搜索引擎的url获取途径都哪些?

​ a、新网站会主动提交。

​ b、在其他网站设置的外链也会加入到待爬取的url队列里面。

​ c、和dns服务商合作,如果有新网站成立,搜索引擎就会获取网址。

​ 第二步:数据存储

​ 第三步:预处理

​ 提取文字

​ 中文分词

​ 消除噪音(比如版权声明文字、导航条、广告等……)

​ 除了HTML文件外,搜索引擎通常还能抓取和索引以文字为基础的多种文件类型,如 PDF、Word、WPS、XLS、PPT、TXT 文件等。我们在搜索结果中也经常会看到这些文件类型。

​ 第四步:提供检索服务,网站排名

(3)搜索引擎的局限性。

​ 1.通用搜索引擎所返回的结果都是网页,而大多情况下,网页里90%的内容对用户来说都是无用的。

​ 2.不同领域、不同背景的用户往往具有不同的检索目的和需求,搜索引擎无法提供针对具体某个用户的搜索结果。

​ 3.万维网数据形式的丰富和网络技术的不断发展,图片、数据库、音频、视频多媒体等不同数据大量出现,通用搜索引擎对这些文件无能为力,不能很好地发现和获取。

​ 4.通用搜索引擎大多提供基于关键字的检索,难以支持根据语义信息提出的查询,无法准确理解用户的具体需求。

2、聚焦爬虫:在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息。

3、爬虫的准备工作。

(1)robots协议(重点)

​ 定义:网络爬虫排除标准

​ 作用:网站通过Robots协议告诉【搜索引擎】哪些页面可以抓取,哪些页面不能抓取。

​ 将来写爬虫程序我们要规避robots协议即可。

(2)网站地图sitemap

​ sitemap 就是网站地图, 它通过可视化的形式, 展示网站的主要结构。

​ 网上有很多sitemap生成网站:https://help.bj.cn/

(3)估算网站的大小

​ 可以使用搜索引擎来做,比如在百度中使用site:www.zhihu.com

http协议(重点)

1、http协议:HyperText Transfer Protocol,超文本传输协议

​ 作用:是一种收发html的【规范】。

2、http端口号:80

​ https端口号:443

​ HTTPS (Hypertext Transfer Protocol over Secure Socket Layer)简单讲是http的安全版,在http下加入SSL层。

​ SSL(Secure Sockets Layer 安全套接层)主要用于Web的安全传输协议,在传输层对网络连接进行加密,保障在Internet上数据传输的安全。

​ 数字签证。(也要去在复习复习)。

3、http协议的特点(重点):

​ (1)应用层协议。(最顶层也是和用户交互的层。)

​ (2)无连接:http协议每次发送请求都是独立的。http 1.1以后有一个头:connection:keep_alive.

​ (3)无状态:http协议不记录状态,进而产生了两种记录http状态的技术:cookie和session。

4、url:统一资源定位符。

​ (1)url的作用:用来定位互联网上的【任意】资源的【位置】。

​ (2)url的组成:

​ https://www.baidu.com/s?wd=python&rsv_spt=1

​ https://www.baidu.com/index.html

​ 协议:https/http

​ netloc(网络地址):ip:port

​ ip主要用来定位电脑(网卡)。

​ port主要用来定位应用。mysql(3306),mongo(27017)----相当于一个门户。

​ path:资源在服务器的相对路径。—路由(router)

​ (3)url中的特殊符号。

​ ?:get请求的参数在?后面

​ &:get请求的多个参数用&连接

​ #:锚点,定位到页面中任意位置。

​ (4)python中用来解析url的模块。

​ from urllib import parse

​ url = ‘https://ww.baidu.com:8888/index.html?username=222&password=123#abc’

​ result = parse.urlparse(url)

​ print(result)

​ ‘’’

​ ParseResult(

​ scheme=‘https’,

​ netloc=‘ww.baidu.com:8888’,

​ path=’/index.html’,

​ params=’’,

​ query=‘username=222&password=123’,

​ fragment=‘abc’)

​ ‘’’

​ print(result.scheme)

​ print(result.netloc)

5、http工作过程:(重点)

​ (1)地址解析

​ (2)封装HTTP请求数据包

​ (3)封装成TCP包,建立TCP连接(TCP的三次握手)

(4)客户机发送请求命令

(5)服务器响应

​ (6)服务器关闭TCP连接

6、客户端请求(重要)

​ (1)组成:请求行、请求头部、空行、请求数据(实体)四个部分组成

​ 请求行:协议,url,请求方法

​ 请求头:主要的作用就是来限定这个请求的详细信息。(非常重要,必须要知道一些重要的请求头的含义。)

​ 请求数据:post请求的数据是放到这里面的。

​ (2)重要请求头(针对于爬虫而言)

​ user-agent:客户端标识

​ cookie:请求的状态信息,很重要

​ Referer:表示产生请求的网页来源于哪里。

​ 防盗链。

​ accept:允许传入的文件类型。

​ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3。

​ x-requested-with:ajax请求必须要封装的头

​ --------------------------

​ content-type:post请求的数据类型

​ content-length:post请求数据的长度

​ (3)请求方法:get/post/put(推送)/delete(删除)/trace(诊断)/options(性能)/connect(连接,预留字段)。

​ get方法:get获取–从服务器获取资源–条件(请求参数)—请求参数是拼接到url里面的?后面–不安全(容易被别人获取:用户名和密码)—大小受限。

​ post方法:post传递–向服务器传递数据–请求数据是放在实体里面。----安全—大小不受限

​ 记忆知识,千万不要被–理解记忆。

7、服务器响应(重要)

​ (1)组成:

​ 状态行:状态码

​ 消息报头:

​ 空行

​ 响应正文

​ (2)响应头

​ Content-Type: text/html;charset=utf-8:响应的类型

​ (3)状态码(状态码)(重要)

​ 100~199:表示服务器成功接收部分请求,要求客户端继续提交其余请求才能完成整个处理过程。

​ 200~299:表示服务器成功接收请求并已完成整个处理过程。常用200(OK 请求成功)。 300~399:为完成请求,客户需进一步细化请求。例如:请求的资源已经移动一个新地址、常用302(所请求的页面已经临时转移至新的url)、307和304(使用缓存资源)。

​ 400~499:客户端的请求有错误,常用404(服务器无法找到被请求的页面)、403(服 务器拒绝访问,权限不够—DDos)。

​ 500~599:服务器端出现错误,常用500(请求未完成。服务器遇到不可预知的情况)。

8、当我们在客户端输入一个url,客户端是如何请求加载出整个页面的?(重点)

​ (1)客户端解析url,封装数据包,发送请求给服务器。

​ (2)服务器从请求中解析出客户端想要内容,比如index.html,就把该页面封装成响应数据包,发送给客户端。

​ (3)客户端检查该inde.html中是否有静态资源需要继续请求,比如js,css,图片,如果有继续请求获取静态资源。

​ (4)客户端按照html的语法结合静态资源将页面完美的显示出来。

requests模块(重点)

requests模块简介

Urllib和requests模块是发起http请求最常见的模块。

安装:pip install reqeusts

requests模块的get方法

​ 1、response = requests.get(

​ url=请求url地址,

​ headers = 请求头字典,

​ params=请求参数字典,

​ )

​ 2、response对象

​ (1)响应正文:

​ a、字符串格式的响应正文:response.text

​ b、字节类型(bytes)的响应正文:response.content

​ (2)响应正文的乱码问题解决:

​ response.content.decode(‘页面的正确编码’)

2、案例:百度产品页面下载

问题:下载好的页面打开之后,相比较原来的页面没有图标,为什么?

​ )

​ 2、get请求一般带参数,带参数就将参数封装到params字典中就可以了。

​ 案例:新浪新闻,两种分装params请求参数方式

​ 3、response对象

​ (1)响应正文:

​ a、字符串格式的响应正文:response.text

​ b、字节类型(bytes)的响应正文:response.content

​ (2)响应正文的乱码问题解决:

​ a、encode和decode就是二进制和字符串之间转换方法。

​ 编程里面数据载体

​ 存储用变量或者常量

​ 可以看到数据的内容一定是字符串格式。

​ 正常的计算机数据本质都是二进制–bytes。

​ str.encode(‘编码’)—>bytes《-----》bytes(str,encoding=‘编码’)

​ bytes.decode(‘编码’)---->str《-----》str(bytes,encoding=‘编码’)

​ 乱码:编解码不一致造成的。

​ response.content.decode(‘页面的正确编码’)—得到页面正确的字符串内容

​ b、response.text之所以可以获取字符串格式,其实在requests模块的底层用

​ response.encoding这个属性所对应的编码来将二进制内容变成字符串。其实就是response.encoding所对应的编码错了。只需要指定正确的即可。

​ response.encoding这个属性值值是requests模块自动识别。

​ response.encoding=‘页面正确编码’

​ response.text—》正确的页面内容

​ 如果response.text乱码了,可以先给response.encoding设置正确编码,在通过response.text就可以获取正确的页面内容。

​ 内置函数&内置模块:python自带的模块

​ dir()

​ str()

​ (3)状态码:response.status_code

​ (4)响应头:response.headers

​ 4、分页如何实现?

​ 分页的请求的每一页url基本上都是通过get请求的一个请求参数决定的,所以其实只需要通过get请求的params字典中的分页字段找到规律,就可以了。

​ 案例:百度贴吧分页信息爬取

requests post请求

​ response = requests.post(

​ url = 请求url地址,

​ headers = 请求头字典,

​ data=请求数据字典,

​ )—response对象。

​ 案例:百度翻译案例

​ 破解百度翻译,做到可以查询任意单词效果

数据的分类(将从学习编程到现在,将所有数据建立网络)

分类

(1)结构化数据:能用关系型数据库描述的数据。

​ 特点:数据以行为单位,一行数据表示一、个实体的信息,每一行的数据的属性是相同的。

​ 举例:关系数据库中存储的表

​ 处理方法:sql—结构化查询语言—语言—可以在关系型数据库中对数据的操作。

(2)半结构化数据:拥有自描述结构数据

​ 特点:包含相关标记,用来分隔语义元素以及对记录和字段进行分层----也别成为自描述结构

​ 举例:html,xml,json。

​ 处理方法:正则,xpath(xml,html)

(3)非结构化数据:

​ 特点:没有固定结构的数据。

​ 举例:文档,图片,视频,音频等等,都是通过整体存储二进制格式来保存的。

​ 如果下载视频,音频。

​ 处理:

​ response = requests.get(url=‘视频的地址’)

​ 保存response.content即可,文件名称后要注意。

json(json(JavaScript Object Notation,JS对象标记))数据

​ json是一种数据【交换】的格式。

​ json是如何来进行交换的。

​ 【json其实是在js语言中,用’字符串’的形式来表示json中的对象和数组的一种技术。】所以json本质上是字符串。

​ js中的对象:var obj = {name:‘zhangsan’,age:‘10’}----在python中这个可以当成:字典

​ js中的数组:var arr = [‘a’,‘b’,‘c’,‘d’]----在python中这个可以当成:list。

json数据的处理(重点)

​ (1)使用json模块处理。

​ json_str:json数据

​ json.loads(json_str)—>python的list或者字典

​ json.dumps(python的list或者字典)—>json_str

​ (2)在requests模块中,response对象有个json方法,可以直接得到相应json字符串解析后的内容

​ response.json()—>python的list或者字典

json作用

​ JSON作为数据包格式传输的时候具有更高的效率,这是因为JSON不想xml那样具有严格的闭合标签,这就让有效数据量与总数据包比大大提升,从而减少同等数据流量的情况下,网络的传输的压力大大减低。

cookie和session

什么是cookie和session?

​ cookie是网站用来辨别用户身份,进行会话跟踪,存储在本地终端上的数据。

​ session(会话)起来本含义是指有始有终的一系列动作和消息。在web中,session主要用来在服务器端存储特定用户对象会话所需要的信息。

cookie和session产生的原因:

​ http协议是一个无状态协议,在特定操作的时候,需要保存信息,进而产生了cookie和session。

cookie原理:

​ 由服务器来产生,浏览器第一次请求,服务器发送给客户端进而保存。

​ 浏览器继续访问时,就会在请求头的cookie字段上附带cookie信息,这样服务器就可以识别是谁在访问了。

​ 但是cookie存在缺陷:

​ 1、不安全–本地保存,容易被篡改。

​ 2、大小受限,本身最大4kb。

​ cookie虽然在一定程度上解决了‘保持状态’的需求,但是我们希望有一种新的技术可以克服cookie缺陷,这种技术就是session。

session原理:

​ session在服务器保存。----解决安全问题。

​ 问题来了:服务器上的session,但是客户端请求发送过来,服务器如何知道session_a,session_b,到底和那个请求对应。

​ 所以为了解决这个问题:cookie就作为这个桥梁。在cookie有一个sessionid字段,可以用来表示这个请求对应服务器中的哪一个session。

​ 禁用cookie,一般情况下,session也无法使用。特殊情况下可以使用url重写技术来使用session。

​ url重写技术:将sessionid拼接到url里面。

​ session的生命周期:服务器创建开始,有效期结束(一般网站设定都是大约30分钟左右),就删除。

常见误区:打开浏览器中的一个网页,浏览器关闭,这个网页的session会不会失效?

​ 不会,服务器到底删除不删除session,由session的生命周期。有效期结束,就会被删除。

cookie的字段

​ (1)Name : 该的名称。一旦创建, 该名称便不可更改。

​ (2)value : 该cookie 的值。如果值为Unicode 字符, 需要为字符编码。如果值为二进制数据, 则需要使用BASE64 编码。

​ (3)Domain : 可以访问该cookle 的域名。例如, 如果设置为.zhihu.com , 则所有以zhihu.com 结尾的域名都可以访问该cookie。

​ (4)MaxAge : 该cookie 失效的时间, 单位为秒, 也常和Expires一起使用, 通过它可以计算出其有效时间。Max Age 如果为正数, 则该cookie 在Max Age 秒之后失效。如果为负数, 则关闭浏览器时cookie 即失效, 也不会以任何形式保存该cookie 。

​ (5)Path : 该cookie 的使用路径。如果设置为/path/ , 则只有路径为/ path / 的页面可以访问该cookie 。如果设置为/ , 则本域名下的所有页面都可以访问该cookieo

​ (6)Size 字段: 此Cookie 的大小。

​ (8)HTTP 字段: cookie 的httponly 属性。若此属性为true , 则只有在HTTP 头中会带有此Cookie 的信息, 而不能通过document.cookie 来访问此Cookie。

​ (9)Secure : 该cookie 是否仅被使用安全协议传输。安全协议有H TTP s 和SSL 等, 在网络上传输数据之前先将数据加密。默认为false。

会话cookie和持久cookie

会话cookie:Max Age 为负数,则关闭浏览器时cookie 即失效,保存在内存中的cookie。

持久cookie:Max Age 如果为正数, 则该cookie 在Max Age 秒之后失效。保存在硬盘上的cookie

持久化:将内存中数据持久化到硬盘上。其实就是数据保存到文件或者数据库中。

内存主要的作用就是由于速度快速度快,启动应用软件或者程序的时候,就会分配一定内存空间作为该程序运行内存。

内存一旦断点,就会被清空。

序列化:将对象持久化到硬盘中。

用requests登录页面。

(1)将登录后的cookie封装到请求头字典中,这样就可以了。

​ 案例:人人网登录

代理

代理作用

​ 192.168.0.101

​ (1)突破自身IP 访问限制, 访问一些平时不能访问的站点。

​ (2)访问一些单位或团体内部资源: 比如使用教育网内地址段免费代理服务器, 就可以用于对教育网开放的各类FTP 下载上传, 以及各类资料查询共享等服务。

​ (3)提高访问速度:通常代理服务器都设置一个较大的硬盘缓冲区, 当有外界的信息通过时, 同时也将其保存到缓冲区中, 当其他用户再访问相同的信息时, 则直接由缓冲区中取屮信息传给用户, 以提高访问速度。

​ 4、隐藏真实IP : 上网者也可以通过这种方法隐藏自己的IP , 免受攻击。对于爬虫来说, 我们用代理就是为了隐藏自身IP , 防止自身的被封锁。

代理的分类

​ (1)根据协议区分

​ 根据代理的协议, 代理可以分为如下类别。

​ FTP 代理服务器:主要用于访问FTP 服务器, 一般有上传、下载以及缓存功能, 端口一般为21 、2121 等。

​ HTTP 代理服务器:主要用于访问网页, 一般有内容过滤和缓存功能, 端口一般为80 、8080 、3128 等。

​ SSL/TLS 代理:主要用于访问加密网站, 一般有SSL 或TLS加密功能( 最高支持128 位加密强度) , 端口一般为443 。

​ RTSP 代理:主要用于访问Real 流媒体服务器, 一般有缓存功能, 端口一般为554 。

​ Telnet 代理:主要用于telnet 远程控制( 黑客人侵计算机时常用于隐藏身份),端口一般为23 。

​ POP3/SMTP 代理:主要用于POP3/SMTP 方式收发邮件, 一般有缓存功能, 端口一般为110 / 25 。

​ SOCKS 代理:只是单纯传递数据包, 不关心具体协议和用法, 所以速度快很多, 一般有缓存功能, 端口一般为1080 。SOCKS 代理协议又分为SOCKS4 和SOCKS5 , 前者只支持TCP ,而后者支持TCP 和UDP , 还支持各种身份验证机制、服务器端域名解析等。简单来说,SOCKS4 能做到的SOCKS5 都可以做到, 但SOCKS5 能做到的SOCKS4 不一定能做到。

​ (2)根据匿名程度区分

​ 根据代理的匿名程度, 代理可以分为如下类别。

​ 高度匿名代理: 会将数据包原封不动地转发, 在服务端看来就好像真的是一个普通客户端在访问, 而记录的IP 是代理服务器的IPO

​ 普通匿名代理: 会在数据包上做一些改动, 服务端上有可能发现这是个代理服务器, 也有一定几率追查到客户端的真实伊代理服务器通常会加人的HITP 头有HTTP_VIA 和HTTP_X_FORWARDED FOR 。

​ 透明代理:不但改动了数据包, 还会告诉服务器客户端的真实IPO 这种代理除了能用缓存技术提高浏览速度, 能用内容过滤提高安全性之外, 并无其他显著作用, 最常见的例子是内网中的硬件防火墙。

​ 间谍代理:指组织或个人创建的用于记录用户传输的数据, 然后进行研究、监控等目的的代理服务器。

代理的设置

​ proxies = {

​ ‘http’:‘http://114.99.11.179:9999’,#http和https都可以用http作为key

​ }

​ response = requests.get/post(proxies = proxies)

正则表达式

元字符

匹配边界

​ ^ —行首

​ $—行尾

表示重复次数

​ ? —0或者1

​ * ---->=0

​ + — >=1

​ {n,}—>=n

​ {n,m}—》n,《m

​ {n}—n次

匹配文字

​ []----表示匹配单字符

​ [abc]–匹配a或者b或者c中的其中一个

​ [a-zA-Z0-9]—匹配所有小写,大写和数字中的一个

​ \b—单词的边界

​ \d—表示数字

​ \w–数字、字母下、划线

​ \s—空白字符(空格,换行,制表)

​ .—除换行以外的任意字符

re模块

re模块使用步骤

​ #(1)导包

​ import re

​ #(2)将正则表达式编译成一个pattern对象

​ pattern = re.compile(

​ r’正则表达式’,

​ ‘匹配模式’,#可以不指定,默认就按正则表达式本来的含义进行匹配。

​ )

​ 正则匹配模式:

​ re.S----.可以匹配换行符

​ re.I—忽略大小写

​ #(3)pattern对象的方法(match,search、findall)匹配字符串。

​ match对象的属性:

​ match.group()等价于match.group(0)----返回匹配结果内容

​ match.span()–匹配范围

​ match.start()

​ match.end()

pattern对象的方法

​ (1)match方法:默认从头开始匹配,只匹配一次,返回一个match对象

​ Match对象 = pattern.match(

​ string,#要匹配的目标字符串

​ start,#要匹配目标字符串的起始位置(可选)

​ end#结束位置(可选)

​ )

​ (2)search 方法:全文匹配,只匹配一次,返回一个match对象

​ Match = pattern.search(

​ string,#要匹配的目标字符串

​ start,#要匹配目标字符串的起始位置(可选)

​ end#结束位置(可选)

​ )

​ (3)findall方法:全文匹配,匹配多次,返回一个list

​ list= pattern.findall(

​ string,#要匹配的目标字符串

​ start,#要匹配目标字符串的起始位置(可选)

​ end#结束位置(可选)

​ )

​ (4)finditer方法:全文匹配,匹配多次,返回一个迭代器,迭代器里面存储的是match对象

​ 迭代器= pattern.findall(

​ string,#要匹配的目标字符串

​ start,#要匹配目标字符串的起始位置(可选)

​ end#结束位置(可选)

​ )

​ 什么是迭代器?

​ 当有一种数据或者内容比较多的时候,可以将其分装迭代器。—通过for循环来使用这个迭代器就可以获取其中的每一个数据。

​ 有__next__和__iter__。

​ 可迭代对象?有__iter__方法对象。

​ str

​ bytes

​ list

​ dict

​ tuple

​ 文件流

​ 需求:打印输入文件内容,同时输出行号。

​ (5)split:安正则方法表示内容进行分割字符串,返回分割后子串list

​ Pattern.split(

​ String,

​ Maxsplit#指定最大分隔次数,默认全部分隔,可选

​ )

​ http://www.baidu.com:8080/index.html

​ (6)sub:按照正则表示的内容替换字符串(重要的)

​ Pattern.sub(

​ repl, #替换成什么

​ String,#替换什么

​ Count#替换次数,可选,默认全部替换

​ )—>替换后的字符串

​ (1)repl字符串

​ import re

​ p = re.compile(r’(\w+) (\w+)’)

​ s = ‘hello 123,hello 456’

​ #提前用p去匹配目标串,找到能匹配出来的内容,就是替换找出来的这个内容的。

​ print(p.sub(r’hello world’,s))#使用‘hello world’替换’hello 123’和’hello 456’

​ print(p.sub(r’\2 \1’,s))#引用分组

​ (2)当repl是一个函数的时候,这个函数是有要求的:

​ a、必须带一个参数,这个参数其实就是提前用p去匹配目标串,得到match对象。

​ b、这个函数必须有返回值,返回值是一个字符串,这个字符串将来就作为替换的内容。

分组

​ 分组在正则表达式中就是用()来表示的。一个括号就是一个分组。分组的作用主要有以下两个:

​ (1)筛选特定内容

​ (2)引用分组

贪婪非贪婪模式

​ (1)贪婪是用*来控制,python默认是贪婪模式,所以默认所有的数量控制符都是取所能匹配的最大值。

​ (2)非贪婪是用?来控制的,?放在数量控制符后面,表示数量控制符匹配最小的次数。

​ 5、.*? 大法

非负整数 0 90 ^\d+$

匹配正整数 100 29 1\d*$

非正整数 0 -20 2\d*$

qq邮箱:qq号5位—14 [1-9]\d{4,13}@qq.com

匹配11位电话号码:第一位是1,第二位是3-9第三位开始不限定 1[3-9]\d{9}

匹配日期:比如:2019-12-19 3\d{3}-(1[0-2]|0?[1-9])-(3[01]|[12]\d|0?[1-9])$

长度为8-10的用户密码:开头字母:必须大写,每一位可以是数字,字母,_ [A-Z]\w{7,9}

我们学的任何知识,都是在解决前面的问题,或者是优化前面的问题。

正则之所以强大:可以处理任何的文本数据的提取,速度非常快

xpath(语法)

什么是xml?

1、定义:可扩展标记性语言(EXtensible Markup Language)

2、特定:xml是具有自描述特性的半结构化数据。

3、作用:xml主要用来传输数据

xml和html的区别?

语法要求不同:xml的语法要求更严格。

​ (1)在html中不区分大小写,在xml中严格区分

​ (2)在html中,有时不严格,如果上下文清楚地显示出段落或者列表键在何处结尾,那么你可以省略

或者标记。在xml中,是严格的树状结构,绝对不能省略任何标记。

​ (3)在xml中,拥有单个标记二没有匹配的结束标记的元素必须用一个/字符作为结尾。

​ (4)在xml中,属性值必须分装在引号中。在html中,引号可用可不用。

​ (5)在html中属性名可以不带属性值,xml必须带

​ (6)xml文档中,空白部分不会被解析器自动删除,但是html是过滤掉空格的

标记不同

 ·(1)html使用固有的标记,xml没有固有标记

​ ·(2)html标签是预定义的,xml标签是自定义的、可扩展的。

作用不同

​ (1)html的设计宗旨是用来显示数据。

​ (2)xml使用来传输数据的。

xpath(语法)–就相当于一个路径一样–重点

什么xpath?

​ xpath就是用来筛选html或者xml中元素语法。

xml和html中一些名字。

​ 元素

​ 标签

​ 属性

​ 内容

xpath的语法

​ (1)选取节点

​ . --当前节点

​ … —代表父节点

​ /—从根节点开始选

​ // —从文档中的任意位置

​ nodename—选取标签或元素

​ @属性名—选取属性名所对应的属性值

​ text()----选取内容

​ (2)谓语:语言中就是用来限定主语的成分。

​ a、可以通过位置限定

​ [数字]选取第几个----//body/div[3]

​ [last()]:选取最后一个//body/div[last()]

​ [last()-1]:选取倒数第二个//body/div[last()]

​ [position()>1]:选取位置大于1----//dl/dd[position()>1]

​ b、通过属性限定

​ [@class=‘属性值’]:选取class属性等于属性值的。----//div[@class=“container”]

​ c、通过子标签的内容来限定

​ //book[price>35]–选取book标签的price字标签的内容大于35的book标签。

​ (3)通配符:*

​ @*—任意属性

​ * —任意节点

lxml模块:python用来解析xml和html模块,用这个模块就可以使用xpath语法。

第三方模块:pip install lxml

C:\Anaconda3\Lib\site-packages

xpath方法返回的都是列表,查元素和标签的时候装的是对象,查属性和元素的时候,装的是字符串?

1、爬虫项目分析流程。—第一阶段完成

见图片

爬虫和反爬的斗争—反爬策略(重点)

反爬策略

(1)通过user-agent客户端标识来判断是不是爬虫。

​ 解决的办法:封装请求头:user-agent

(2)封ip

​ 设置代理ip

(3)通过访问频率来判断是否是非人类请求。

​ 解决的办法:设置爬取间隔和爬取策略。

(4)验证码

​ 解决办法:识别验证码

(5)页面数据不再直接渲染,通过前端js异步获取

​ 解决办法:a通过selenium+phantomjs来获取数据

​ b找到数据来源的接口(ajax接口)

页面中的技术

​ (1)js:他是一种语言。

​ 获取页面的元素,可以对这些页面元素做些操作。

​ 网络数据的获取

​ (2)jquery:他就是一个js库,这个库可以使得js编程变得轻松容易。

​ (3)ajax

​ 同步请求和异步请求。

selenium+phantomjs(重点)

解决办法:如果想要解决页面js的问题,主要需要一个工具,这个工具(具备浏览器的功能)可以帮助我们来运行获取到的js。

什么selenium?

​ selenium是一个web自动化测试工具。但是他本身不带浏览器的功能,他这工具就相当于一个驱动程序,通过这工具可以帮助我们自动操作一些具有浏览器功能外部应用。

什么是phantomjs?

​ phantomjs就是内置的无界面浏览器引擎。他可以像浏览器那样加载页面,运行页面中的js代码。

​ chromedriver.exe这个是谷歌浏览器驱动程序,通过这个程序可以使得selenium可以调用chrome浏览器。—有界面浏览器。

​ 这两个的功能有界面的更加强大:很多网站还是可以识别你是不是用phantomjs来进行爬取的,也会被禁。

​ 但是有界面的chrome浏览器是不会被禁的,他就像一个真正用户在请求一样。

selenium和phantomjs的安装。

​ (1)下载phantomjs和chromedriver.exe

​ 搜索phanomjs镜像

​ (2)安装:

​ 解压

​ 找到两个压缩包中exe文件,将其复制到anaconda/Scripts目录下面就ok了。

​ C:\Anaconda3\Scripts

​ C:\Anaconda3

​ (3)测试:

​ 在cmd中输入:phantomjs

​ chromedriver

​ (4)selenium安装:pip isntall selenium==2.48.0

python的anaconda安装

path路径:里面的路径就是为了在cmd中进行命令输入时候进行exe工具查找。

python的安装最重要的两个工具:

​ python.exe

​ pip.exe----最重要

where pip 可以查看哪些路径下面有pip,在配置环境变量的时候,把anaconda的C:\Anaconda3\Scripts方法系统path环境变量最最前面。

python多版本共存问题:

​ python2,python3,怎么一起使用?

​ python2:pip2.exe----pip2 install

​ python3:pip3.exe----pip3 install

​ anaconda— conda_pip

​ python —pip

​ python.exe

​ pip.exe----最重要

​ 当环境变量path更改之后,需要重启cmd。

文档:selenuim常用方法总结.note

链接:http://note.youdao.com/noteshare?id=0142a95cf23fadbaea95809ccb5674b2&sub=02896A50836E4995997A821419D9A063

文档:selenium的三种等待.note

链接:http://note.youdao.com/noteshare?id=8f6a0765e4017a4140a05485a9d80a48&sub=48D9761ED13A49EDAC64D180C8340613

分析ajax请求最重要的是参数。所以在分析ajax的主要方向就是找到参数的意义的实现方法。

反爬策略

(1)通过user-agent客户端标识来判断是不是爬虫。

​ 解决的办法:封装请求头:user-agent

(2)封ip

​ 设置代理ip

​ 封ip最主要的原因就是请求太频繁。让人家发现你了。

(3)通过访问频率来判断是否是非人类请求。

​ 解决的办法:设置爬取间隔和爬取策略。

(4)验证码

​ 解决办法:识别验证码

(5)页面数据不再直接渲染,通过前端js异步获取

​ 解决办法:a通过selenium+phantomjs来获取数据

​ b找到数据来源的接口(ajax接口)

(6)能获取列表页,就不获取详情页,为了避免增加请求的数量。

​ 将详情页放到每条数据中心,第一次爬取先爬取列表。

​ 第二次在从数据库中拿出详情页链接,在做第二次爬取。

(7)能一次性获取,就不分页获取,正对ajax请求。可以将每一页获取数量调大。

多线程爬虫

程序、进程和线程。

​ 程序:就相当于一个应用。

​ 进程:程序运行资源(内存资源)分配的最小单位,一个程序可以有多个进程。

​ 线程:cpu最小的调度单位,必须依赖进程而存在。线程没有独立资源,所有线程共享该进程的全部资源。

​ 线程的划分尺度比进程更小。

为什么多进程和多线程可以提高程序的运行速度?

提高程序的运行速度的第一种方法

提高cpu的利用率。

​ 解决的方式:cpu不用休息就可以做到。

​ 现在我们的程序有一个线程。cpu就只处理他。

​ 如果在程序中遇到:阻塞。一旦阻塞了,cpu就休息了。休息的这段时间,就浪费了cpu的资源。

​ 有两种方式可以阻塞:time.sleep()

​ 遇到io

​ 多线程:多个任务。cpu会在这多个任务之间切换,如果其中一个线程阻塞了,cpu不会休息,会处理其他线程。

提高程序运行速度第二种方法

增加cpu,让每个cpu处理一个任务。

​ cpu的多核的。—利用cpu的多核进行解决。—cpu每一个核处理一个进程。–用多进程去处理。

并发和并行。

​ 《操作系统原理》

​ 《编译原理》

​ 《数据结构和算法》

​ 全局性解释锁:python多任务处理效率并不好。

​ cpython–c语言实现的编译器—默认。

​ jpython—java实现的

​ pypython–python语言实现的。

​ 区块链:公共记事账本。去中心化的数据库----分布式数据库。

​ go语言很火:天生支持并发。

什么是多线程:程序中包含多个并行执行流。

python中的threading模块

一个功能的实现不外乎就两种:调用别人接口,自己丰衣足食

多线程的开启方法

​ (1)使用threading模块的方法

​ t = threading.Thread(

​ target=线程执行的任务(方法)名字,

​ args = 执行方法的参数,是一个元组

​ )—创建线程

​ t.start()—启动线程

​ (2)使用自定类的形式来创建线程

​ 利用面向对象继承的思想。

​ 子类继承父类,子类拥有父类非私有的任何资源。

​ 程序在运行时,当子类调用一个方法或者属性的时候,先去子类中找,如果找不到,就一层层向上,取父类中找。(继承具有传递性)

​ 自定义线程类:

​ a、继承threading.Thread–拥有功能

​ b、保证父类的init方法能够被调用。

​ 如何调用父类的init方法:

​ super().init()

​ threading.Thread.init(self)

​ 用类取创建线程的步骤:

​ 1、继承Thread

​ 2、重写run方法

​ 3、实例化线程类,就相当于创建一个线程,用这个对象调用start()方法就可以启动这个线程

​ 4、如果自定义线程类要实现init方法,必须先调动父类的init方法。

线程的名称:可以帮我们测试时那个线程做的哪件事。

​ 线程对象.name查看:默认是Thread-1,Thread-2…

​ 自定名称:其实就是给self.name赋值

查看线程的数量

​ threading.enumerate()–可以查看当前进程中的线程的数量

线程的执行顺序是混乱的。

原因是:线程的状态决定的。

死锁的条件:

​ 死锁的发生会让程序永久阻塞。

​ (1)同一个线程,先后获取两次锁对象,在第二次获取所对象时,会死锁。

​ (2)线程a拥有锁1,线程b拥有锁2,线程a在不释放锁1的情况下,试图获取锁2,线程b在不释放锁2情况下试图获取锁1,此时在获取对方锁的时候,会发生死锁。

多线程和多进程

功能:

​ 多线程和多进程都能做到多任务。

定义:

​ 进程:程序运行资源(内存资源)分配的最小单位,一个程序可以有多个进程。

​ 线程:cpu最小的调度单位,必须依赖进程而存在。线程没有独立资源,所有线程共享该进程的全部资源。

区别:

​ (1)关系:一个程序至少有一个进程,一个进程至少有一个线程.

​ (2)有无资源:进程拥有独立资源,线程依赖于进程,没有独立资源,所有该进程的线程共享所在进程的所有资源。

​ (3)划分尺度:线程的划分尺度小于进程(资源比进程少),使得多线程程序并发性更高。

优缺点:

​ 线程:线程的执行开销小,但不利于资源的管理和保存。

​ 进程:多个进程之间相互独立,不利于进程间信息交互。进程拥有独立资源。

​ 在设计数据交互频繁的场景,多进程比多进程更加适合。

​ 在并发程度上,多进程比多线程的效率更高。

如何选择:应该按照实际开发情况进行选择。多进程和多线程相结合的方式来作为多任务编程。

GIL:cpython就内置。—很多模块或者开发者刚开始觉得他好,所以在很多模块内置GIL作为多线程数据处理的锁机制。

​ GIL效率低,觉得不好,也没办法了。

join()–阻塞方法—阻塞当前进程。

mongoDB

mongodb内部执行引擎是js,所以可以使用js代码

服务端客户端命令

mongo:客户端

​ mongo --host-h --port-p

mongod:服务端

​ mongod --dbpath(数据库存放数据的位置)

​ 服务器就相当于一个数据库程序,程序可以绑定在多个端口上,每个端口就相当于启动一个服务器。

客户端和服务端到底是啥

​ 数据库一般都有客户端和服务端命令,

​ 服务端:相当于启动这个数据库,比如启动mongo,mysql,启动之后,你才能CRUD。

​ cmd开启,开启之后这个cmd窗口就相当于一个服务端程序,你不能关闭,关闭之后数据库就关闭了。

​ 客户端:就相当于链接数据库的窗口,连接好之后,就可以进行CRUD操作了。

​ c\s架构。

任务:关闭mongo服务,手动开启两个服务器,一个绑定27018,一个绑定27019,并分别用客户端连接他们。

基础命令

show dbs 查看当前的数据库

use databaseName 选库

show collections 查看当前库下的collection,show tables

crud

高级操作

Redis

redis数据库运行在内存上,可以持久化到硬盘。

当redis启动的时候,就会从硬盘上读出数据,全部加载到内存中,让用户使用。

数据结构丰富

数据结构都有哪几种。

每一种的结构要有清晰直观的概念。

每种数据结构优势还有作用都有哪些。

hash表:[{},{},{}]

stringvalue

list:[1,2,3,4,5,6]

set:{a1,a2,a3}–不重复。

可以持久化到硬盘。

掌握持久化机制。

scrapy框架

https://www.cnblogs.com/saoqiang/p/12450106.html#%E6%B5%81%E7%A8%8B分布式爬虫笔记

框架的功能和优势

scrapy框架功能:爬虫框架,可以简单快速的实现一个爬虫。

优势:

​ 现在我们可以手动实现一个爬虫,框架有优势采取学习。

​ 爬取速度很快,底层是通过异步框架来实现的。—他帮我们已经开好了多线程。

scrapy也不是万能的,自己写的爬虫程序才能万能的。

2、学习框架:

(1)清楚框架组件有哪些。

(2)每个组件的功能是什么–这些组件和代码中的那些文件对应。

(3)组件之间的数据流转。—流转的是什么,组件中对应是哪个方法接受的。

组件

(1)spiders组件:爬虫组件

​ 爬虫程序中,主要可以总结为两部:获取url请求,返回response处理

​ 功能:

​ a、告诉scrapy都下载那些url

​ b、处理下载器下载好的response

(2)Scrapy Engine(引擎):

​ 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。

(3)pipelines:它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.

​ pipeliens.py

​ pipeline是管道的意思。这个管道中流淌数据是item

​ 每个管道主要功能:对item的处理

​ 处理:清洗item

​ item去重

​ 管道的功能是由: def process_item(self, item, spider):

​ 可以设置多个类,每个类中都可以定义process_item。

​ 管道想要生效,必须在settings中配置。

​ ITEM_PIPELINES = {

​ ‘baidu.pipelines.BaiduPipeline’: 300,#300优先级

scrapy命令

下载中间件

爬虫项目:

1*、简单文件*

2*、类*

3*、用多线程爬虫方式*

4*、scrapy爬虫*

5*、scrapy-redis分布式爬虫*

增量爬虫:让数据库中数据,不断以增量形式增长的一种爬虫。

1、如何知道爬取的数据相比于之前是新的–也就是不重复的。

增量爬虫的核心就是去重。

2、如何去重?

​ 用reids去重。–redis速度快,用redis的set查找和插入式O(1),他可以持久化数据,如果之后运行时候,之前的结果也是可以保存查看的。相当于所有的爬取记录,都会被保存下载。–实现简单。

set—>sadd添加一个数据到set集合,如果返回1,表示成功,0表示失败,失败就重复了。

def url_seen(url):—配合hash函数去做

​ re = redis.Redis()

​ result = re.sadd(‘set名称’,url)

​ return result==0

3、在哪里去重?

爬取之前:url—判断url是否重复?

爬取中:response = requests.get(url)—判断页面内容是否爬取过?

爬取后:保存—判断这个内容是否之前保存过?—update方法配合upsert=true

scrapy-redis分布式爬虫部署

1、什么是分布式?

​ 一台机器提高利用率使用多线程或者多进程(多任务策略),来提高cup的执行效率。

​ 一台电脑上执行程序,总有瓶颈。想要突破这种瓶颈,自然想到了使用多台机器。

​ 分布式:使用多台机器共同来完成一个任务,多个机器之间的协调策略,可以通称为分布式。

​ 分布式系统

​ 分布式计算

​ 分布式数据库

2、scrapy-redis分布式的原理

​ 见图

3、安装以及如何部署分布式项目

​ 安装:pip isntall scrapy-redis

(1)主要配置如下:

​ #配置scrapy-redis调度器

​ SCHEDULER = “scrapy_redis.scheduler.Scheduler”

​ #配置url去重

​ DUPEFILTER_CLASS = “scrapy_redis.dupefilter.RFPDupeFilter”

​ #配置优先级队列

​ SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.PriorityQueue’

​ ITEM_PIPELINES = {

​ #如果配置redispipelines,就会将item数据保存到redis中。

​ ‘scrapy_redis.pipelines.RedisPipeline’: 300

​ }

​ #主机名

​ REDIS_HOST = ‘主机的ip’

​ ##端口号

​ REDIS_PORT = 6379

(2)部署流程:

​ 1、导入from scrapy_redis import spiders包

​ spiders继承spiders.RedisSpider

​ 2、start_urls注释掉,设置redis_key = ‘picture_caixi:start_urls’

​ redis-key就表示将来scrapy启动,会去这个key所指定的redis的list中取任务url。

​ 3、添加配置:

​ 这三条主机和从机都要添加

​ #配置scrapy-redis调度器

​ SCHEDULER = “scrapy_redis.scheduler.Scheduler”

​ #配置url去重

​ DUPEFILTER_CLASS = “scrapy_redis.dupefilter.RFPDupeFilter”

​ #配置优先级队列

​ SCHEDULER_QUEUE_CLASS = ‘scrapy_redis.queue.PriorityQueue’

​ ##端口号

​ REDIS_PORT = 6379

​ MONGO_DATABASE = ‘caixi’

​ 主机:

​ #主机名

​ REDIS_HOST = ‘localhost’

​ MONGO_URI = ‘localhost’

​ 【主机才负责初始化redis的任务列表】

​ 从机里面: 主机ip要确定

​ REDIS_HOST = ‘目标主机的ip’

​ MONGO_URI = ‘目标主机的ip’

在启动scrapy-redis分布式项目之前,一定要远程连接一个主机的mongo和redis

4、scrapy-redis源码

4、scrapy-redis源码

爬虫监控

(1)爬虫监控的由来:

爬虫监控相当于监控(自动)一个爬虫,由于爬虫可能会出现一些问题:页面结构变化,加载方式改变等等,就会造成获取数据大部分都为空。对于这种情况,如果能有一个类似监控的东西告诉我们是哪个代码出问题了,这样解决起来就很方便。

(2)监控如何实现?

可以通过发邮件的形式。

爬虫监控的重点就是发邮件。

验证码

(1)用pysseract库来识别验证码—tesseract(orc工具)


  1. 1-9 ↩︎

  2. 0- ↩︎

  3. 1-9 ↩︎

你可能感兴趣的:(爬虫,爬虫)