爬虫-cookie和session、数据、正则表达式

一、cookie和session

  1. 产生的原因:
    由于http是一个无状态的协议每次请求需要之前请求的一些信息,此时必须重新发送之前的请求。为了解决这种问题,产生了一种记录状态的技术,就是cookie和session。

  2. cookie是在客户端记录状态。session是在服务端记录状态。

  3. 在做爬虫的时候,如果要实现登录,只需要将浏览器中登录后的cookie信息封装到请求头中就可以实现登录了

  4. 对于session会话,其本来的含义是指有始有终的一系列动作/消息。而在web中,会话对象用来存储特定用户会话所需的属性及配置信息

    • 当客户端发送一个cookie,服务器会从这个cookie中找到sessionId,在查找出响应session信息返回给客户端,来进行用户页面的流转。如果通过sessionId来查找session,发现没有session,因为第一次登录,创建了一个session。在session有效期内,继续访问该页面,服务器就会直接查找到这个session返回给客户端。
    • session什么时候失效呢?
      • 当session的失效时间达到时失效,一般是30分钟
  5. cookie指某些网站为了辨别用户身份、进行会话跟踪而存储在用户本地终端上的数据

  6. cookie和session一般是配合使用的。当cookie被用户禁用,session怎么使用?

    • 有两种方法:
      1. 提示他必须开启
      2. 使用url重传。 就是将sessionId附带url后面传递给服务器
  7. cookie的组成:

    • Name : 该cookie的名称。一旦创建, 该名称便不可更改。
      value : 该cookie 的值。如果值为Unicode 字符, 需要为字符编码。如果值为二进制数据, 则需要使用BASE64 编码。
    • Domain : 可以访问该cookle 的域名。例如, 如果设置为.zhihu.com , 则所有以zhihu.com 结尾的域名都可以访问该cookie。
    • MaxAge : 该cookie 失效的时间, 单位为秒, 也常和Expires— 起使用, 通过它可以计算出其有效时间。Max Age 如果为正数, 则该cookie 在Max Age 秒之后失效。如果为负数, 则关闭浏览器时cookie 即失效, 浏览器也不会以任何形式保存该cookie 。
    • Path : 该cookie 的使用路径。如果设置为/path/ , 则只有路径为/ path / 的页面可以访问该cookie 。如果设置为/ , 则本域名下的所有页面都可以访问该cookieo
    • Size 字段: 此Cookie 的大小。
    • HTTP 字段: cookie 的httponly 属性。若此属性为true , 则只有在HTTP 头中会带有此Cookie 的信息, 而不能通过document.cookie 来访问此Cookie。
    • Secure : 该cookie 是否仅被使用安全协议传输。安全协议有H TTP s 和SSL 等, 在网络上传输数据之前先将数据加密。默认为false。
  8. 会话cookie和持久cookie
    会话cookie:指存储在浏览器内存中的cookie,当浏览器关闭,会话cookie失效。
    持久cookie:保存在硬盘上的cookie
    这两种cookie的分配标准主要是通过maxAge或者expires这个cookie的字段来定义,负数–cookie

  9. 在爬虫中登录的实现方法有两种:

    1. 在请求头中封装登录后页面中的cookie
    2. 使用requests和session对象,做到登录
      session = requests.session()
      这个session对象可以记录登录状态
  10. 代理:代理服务器,proxy server

    • 功能:代理网络用户去取得网络信息,是网络信息的中转站。
    • 代理的基本原理:正常请求一个网站时,发送请求给web服务器,web服务器发送响应给本机。设置代理服务器后,相当于在本机和服务器之间搭建了一个桥,此时本机不会直接向web服务器发起请求,而是向代理服务器发出请求,代理服务器再发送给web服务器,接着代理服务器再把web服务器的响应发送给本机。这样也可以正常访问页面。
      web服务器识别出的ip就不是本机ip,成功实现ip伪装。
    • 代理的作用
      • 突破自身ip访问限制,访问一些平时不能访问的站点
      • 访问一些单位或团体内部资源:
        比如使用教育网内地址段免费代理服务器,就可以用于对教育网开放的各类FTP下载上传,以及各类资料查询共享等服务
      • 提高访问速度:通常代理服务器都设置一个较大的硬盘缓冲区,当其他用户再访问相同的信息时,直接从缓冲区中取出信息传给用户,以提高访问速度
      • 隐藏真实ip:上网者可以通过这种方法隐藏自己的ip,免受攻击,防止自身被封锁。
    • 代理的分类
      • 根据协议区分
        • 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 不一定能做到。
      • 根据匿名程度区分
        • 高度匿名代理:会将数据包原封不动地转发
        • 普通匿名代理: 会在数据包上做一些改动, 服务端上有可能发现这是个代理服务器, 也有一定几率追查到客户端的真实伊代理服务器通常会加人的HITP 头有HTTP_VIA 和HTTP_X_FORWARDED FOR 。
        • 透明代理:不但改动了数据包, 还会告诉服务器客户端的真实IPO 这种代理除了能用缓存技术提高浏览速度, 能用内容过滤提高安全性之外, 并无其他显著作用, 最常见的例子是内网中的硬件防火墙。
        • 间谍代理:指组织或个人创建的用于记录用户传输的数据, 然后进行研究、监控等目的的代理服务器。

二、数据

(一)数据的分类

1、结构化数据

数据以行为单位,一行数据表示一个实体的信息,每一行数据的属性是相同的。常见的关系型数据库中以表存储的数据就是结构化的数据

2、半结构化数据

结构化数据的一种形式,并不符合关系型数据库或其他数据表的形式关联起来的数据模型结构,但包含相关标记,用来分隔语义元素以及对记录和字段进行分层。因此也被称为自描述的结构。

常见的半结构化数据有:xml、html、json

3、非结构化数据

没有固定的结构,常见的非结构化数据有:文档、图片、视频等。

对于非结构数据,一般通过整体存储二进制格式

(二)json数据

json是js对象的字符串表达式,使用文本形式表示一个js对象的信息。

js的对象相当于python中的字典

js的数组相当于python中的列表

因为json用来存储js的对象或者数组,所以在python中可以将json转化为list或者dict

解析json的包json:

  • json.dump(python的list或dict)---------返回值为json字符串
  • json.loads(json字符串)--------返回值为python的list或者dict
  • json.dump(list/dict,fp)--------list或dict保存到json文件中
  • json.load(fp)--------list/dict:从json文件中读出json数据

三、正则表达式

(一)元字符

  1. 匹配边界
    • 符号 说明
      ^ 行首
      $ 行尾
  2. 重复次数
    符号 说明
    ? 0或1
    •  >=0    
      
    •  >=1    
      
    {n,} >=n
    {n,m} >=n,<=m
    {n} 重复n次
  3. 各种字符的表示
    字符 说明
    [] 表示单字符
    [abc] 匹配a\b\c其中的一个
    [a-z]
    [0-9a-zA-Z]
    \d 数字
    \w 数字、字母、下划线
    \s 空白字符(空格,指表,换行)
    \b 单词的开始和结束
    . 匹配任意字符,除换行符以外

(二)re模块使用的步骤

  1. 将正则表达式编译成一个pattern对象
    pattern=re.compile(‘正则表达式’)
  2. pattern提供一系列的方法,来对文本进行匹配,一半返回一个match对象
  3. 通过使用match对象提供的方法来获取匹配结果
    match对象有以下方法:
    方法 说明
    match.group(0) 获取匹配结果
    match.group() 获取匹配结果
    match.span() 获取匹配范围
    match.start() 匹配开始位置
    match.end() 匹配结束位置

(三)pattern对象的方法

1、match方法

默认从头开始匹配,只匹配一次,返回一个match对象

pattern.match(
	'要匹配的字符串',#必须指定
	start,#匹配的开始位置
	end,#匹配的结束位置
)

import re

pattern = re.compile(r'\d+')
content = 'sjdhgr12356dsitn45656'
m1 = pattern.match(content)
m2 = pattern.match(content,6)
m3 = pattern.match(content,6,8)
print(m1)
print(m2)
print(m3)

print(m2.group())
print(m3.group(0))
print(m2.span())
print(m2.start())
print(m2.end())

2、serach方法

从任意位置匹配,只匹配一次,返回一个match对象

pattern.serach('要匹配的字符串',start,end,)

import re
content = 'asd123qwe456zxc789'
pattern = re.compile(r'\d+')
s1 = pattern.search(content)
s2 = pattern.search(content,6,15)
print(s1)
print(s1.group())
print(s2.group())

3、findall

全文匹配,将匹配到的结果放到一个list中返回,多次匹配

pattern.findall('要匹配的字符串',start,end,)

import re
pattern = re.compile(r'\d+')
content = 'qwe12345axs789 160'
fa = pattern.findall(content)
print(fa)

4、finditer

全文匹配,多次匹配,返回一个包含匹配结果的迭代器

pattern.finditer('要匹配的字符串',start,end,)

import re
pattern = re.compile(r'\d+')
content = 'qwe123456qwe789 034'
fd = pattern.finditer(content)
for i in fd:
    print(i.group())

5、split

切分字符串,按照整个表达式所指定的内容切分

str.split(',')#以,进行切分
pattern.split('要切分的字符串',切分次数)#不指定就是默认,默认全部切割

import re
pattern = re.compile(r'[\s,;]+')
content = 'a,b,,; c;d'
s = pattern.split(content)
print(s)

6、sub

用指定的字符串,替换正则表达式匹配到的目标字符串的内容

pattern.sub(
	repl,#替换成什么
	content,#替换哪个
	count,#替换次数,默认替换所有
)

import re
content = 'hello 123123,hello 456456'
pattern = re.compile(r'\d+')
res = pattern.sub('hi',content)
print(res)

content = 'age:"20"'
def add(match):
    return (str(int(match.group())+2))
res = pattern.sub(add,content)
print(res)
  • repl可以使字符串,也可以是函数
    • 当repl是函数的时,这个函数有以下要求:
      1. 函数必须带一个参数,match对象
        def func(match):
        ‘’’
        对match对象的操作
        ‘’’
        print(match.group())
      2. 当在sub方法里面传入这个参数时,这个match对象其实就是用正则匹配到的每一个match对象
      3. 这个函数是有返回值的,返回值必须是一个字符串,将来是用这个字符串进行替换目标字符串的

(四)正则表达式中的分组

分组时通过 ( ) 来表示的,一个括号就表示一个分组

分组的作用:

  1. 筛选特定内容

    • 取分组内容可以通过match对象的group方法
      match.group(1) # 表示取正则表达式中第一个括号的内容,以此类推
      import re

      content = '{name:"zhangsan",age:"10",hobby:["basktball","football","read"]}'
      pattern = re.compile(r'{name:"(\w+)",age:"(\d+)".+')
      match = pattern.search(content)
      print(match.group(1))#zhangsan
      print(match.group(2))#10
      
  2. 可以在同一个表达式的后面引用前面的分组表达式
    import re

    s = "

    正则表达式

    " pattern = re.compile(r'<(html)><(h1)>(.*)') match = pattern.search(s) print(match.group()) # 正则表达式

(五)正则表达式的模式

pattern = re.compile(
	'正则表达式',
	'正则表达式的模式'
)

正则表达式的模式有以下几种:

模式 说明
re.I 使匹配对大小写不敏感
re.M 多行匹配,影响^和$
re.S 使 . 匹配包括换行在内的所有字符

(六)贪婪模式和非贪婪模式

  • 贪婪模式 *
  • 非贪婪模式 ?
  • *和?都是表示元字符中重复次数
  • 正则默认贪婪,数量控制符也默认贪婪
  • 非贪婪:在表示重复的元字符后加?,取这个重复元字符的最小值

(七)通用匹配正则表达式

. * ? 配合re.S

import re

content = '{name:"zhangsan",age:"10",hobby:["basktball","football","read"]}'
pattern = re.compile(r'.*?"(.*?)".*?"(.*?)".*?')
match = pattern.search(content)
print(match.group())
print(match.group(1))
print(match.group(2))

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