一 、爬虫的认识与http

互联网应用架构

 一般采用c/s架构,b/s架构或者m/s架构
 c/s 即 client server 客户端 服务端
 b/s 即 browser server 浏览器 服务端
 m/s 即 moblie server 移动端 服务端

爬虫的概念

网络爬虫也叫网络蜘蛛,它特指一类自动批量下载网络资源的程序,这是一个比较口语化的定义。

更加专业和全面对的定义是:网络爬虫是伪装成客户端与服务端进行数据交互的程序。

爬虫的应用

  1. 数据采集

大数据时代来临,数据就是核心,数据就是生产力,越来越多的企业开始注重收集用户数据,而爬虫技术是收集数据的一种重要手段。

  1. 搜索引擎

百度,谷歌等搜索引擎都是基于爬虫技术。

  1. 模拟操作

爬虫也被广泛用于模拟用户操作,测试机器人,灌水机器人等。

请求与响应

 请求(request):客户端(应用程序)/chrome  向服务端发送请求
 响应(response):服务器收到请求后进行分析后将用户所需的数据返回给客户端/chrome
 端口:是用来接受或发送数据

HTTP协议

 http、https协议:
 HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版
 即HTTP下加入SSL层, 简称HTTPS
 
 一次http请求的基本流程是由客户端向服务端发起一次请求(request), 而服务器在接收到以后返回给客户端一个响应(response)。所以一次完整的http请求包含 请求和响应 两部分
 
 http协议是基于tcp/ip通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)通过TCP/IP通信协议来在Client和Server之间建座桥,http请求和响应就在这座桥上传递,请求和响应中包含着相关信息;
 而https是在http协议的基础之上,再加上一层SSL/TLS协议,数据在传输过程中是加密(Secure)的。
 
 http协议的默认监听端口是 80
 https协议的默认端口是 443
 
 http协议版本:目前最常用的是HTTP/1.0和HTTP/1.1;需要注意的是HTTP/1.1是长连接的;在使用socket套接字发送请后,接收求数据时容易阻塞;因此在构造报文时推荐使用HTTP/1.0
 HTTP1.1默认使用长连接,可有效减少TCP的三次握手开销。
 HTTP1.0是没有host域的,HTTP1.1才支持这个参数。
 
 HTTP协议请求由什么组成?
 请求行(request line)、请求头部(header)、空行和请求数据四个部分组成
 区别:http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
 
 http是无状态的:无状态等同于不记录来访者的信息
     服务器接收到请求后,为了记录请求方是谁,他其实可以通过set-cookie字段 返回一些特征值或有价值能够确定身份的数据,
     客户端接收到响应后 浏览器会自动将set-cookie中的数据保存下来,下次请求的时候会自动的以cookie字段的形式携带在请求报文中。
     session是基于cookie的;cookie是存储在客户端的数据 Session是存储在服务器上的数据

 

TCP建立连接需要三次握手;断开连接需要四次挥手

TCP三次握手和四次挥手过程

ssh 默认端口22(虚机机) 映射到 1234(本地)端口

 端口:0~65535
 公认端口(Well Known Ports):从0~1023,它们紧密绑定(binding)于一些服务。通常这些端口的通讯明确表明了某种服务的协议。例如:80端口实际上总是HTTP通讯。
 而1024是动态端口的开始。
请求报文格式:

请求方法 路径 协议版本 \r\n请求头部\r\n\r\n

 "GET /search/index?tn=baiduimage&word=动漫 HTTP/1.0\r\nHost: image.baidu.com\r\n\
 Referer: http://www.baidu.com\r\n\r\n"
 # 每加一个请求头在其后加\r\n

 

Content-Type和POST提交数据方式的关系
Content-Type提交数据的方式
application/x-www-form-urlencoded 表单数据
multipart/form-data 表单文件上传
application/json 序列化JSON数据
text/xml XML数据

 

请求方法

 get     请求页面 # 注意get方法最多在url中携带1024字节数据, 一般查询/搜索才用到这种方式
 post 提交数据到指定资源,(提交表单或上传文件)
 put 修改请求
 delete 删除请求

Referer: 该字段的值是当前网页的上一个页面的URL(也就是跳转到当前页面的前一个页面的URL) 注意referer 只要是这个url的父级就可以(https://ibaotu.com/sucai/),也就是说只有域名都可以

 

会话技术

cookie

 http是无状态的,那服务端怎么区分同一个用户的连续请求呢,这就用到了会话技术:cookie和session。
 
 Cookie有时也用其复数形式 Cookies。指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。最新的规范是 RFC6265 。
 
 Cookie其实就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。 服务器在接收到Cookie以后,会验证Cookie的信息,以此来辨别用户的身份。
 
 Cookie可以理解为一个凭证。
 

session

 Session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。这个词在各个领域都有在使用。
 
 而我们web领域,一般使用的是其本义,一个浏览器窗口从打开到关闭这个期间。
 
 Session的目的则是,在一个客户从打开浏览器到关闭浏览器这个期间内,发起的所有请求都可以被识别为同一个用户。而实现的方式则是,在一个客户打开浏览器开始访问网站的时候,会生成一个cookie,SessionID,这个ID每次的访问都会带上,而服务器会识别这个SessionID并且将与这个SessionID有关的数据保存在服务器上。由此来实现客户端的状态识别。因此session是基于cookie的
 
 Session与Cookie相反,Session是存储在服务器上的数据,只由客户端传上来的SessionId来进行判定,所以相对于Cookie,Session的安全性更高。
 
 一般SessionID会在浏览器被关闭时丢弃,或者服务器会验证Session的活跃程度,例如30分钟某一个SessionID都没有活跃,那么也会被识别为失效。
 

 

socket(python 内置库)

socket是应用层与传输层之间的桥

利用socket下载百度图片搜索词为动漫的整个页面的图片

import re
import socket


# 1. 创建一个客户端(socket对象)
client = socket.socket()
# 访问url http://image.baidu.com/search/index?tn=baiduimage&word=%E5%8A%A8%E6%BC%AB

# 2. 连接到对应的服务器(主机)
url = 'image.baidu.com'
client.connect((url, 80))	# 注意connect接收的是一个元组("地址ip", 端口), 即域名

# 3. 构造HTTP请求报文
http_req = "GET /search/index?tn=baiduimage&word=动漫 HTTP/1.0\r\n\
Host: image.baidu.com\r\n\
Referer: http://www.baidu.com\r\n\
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36\r\n\r\n"

# 4. 发送请求
client.send(http_req.encode())		# send只接受字节类型(二进制)的对象。


# 5. 循环接受响应报文的数据
def resp_data(client_obj):
    """
    接受一个创建的客户端对象
    :param client_obj:
    :return: 返回接收的数据
    """
    res = b''
    resp_data = client_obj.recv(1024)
    while resp_data:
        res += resp_data
        resp_data = client_obj.recv(512)
    return res


result = resp_data(client)

# 匹配所有图片的url
img_urls = re.findall('"thumbURL":"(.*?)","replaceUrl"', result.decode(), re.S)
# print(img_url)

# 遍历主机 路径并构造http请求报文
for num, img_url in enumerate(img_urls):
    host = re.findall('http://(.*?)/it', img_url, re.S)[0]
    path = re.findall('\.com(.*)', img_url, re.S)[0]
    # print(host, path)
    client_img = socket.socket()
    client_img.connect((host, 80))

# 构造格式化的请求报文
    http_req = "\
GET {} HTTP/1.0\r\n\
Host: {}\r\n\
Referer: http://image.baidu.com\r\n\
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36\r\n\r\n".format(path, host)
    client_img.send(http_req.encode())
    result_img = resp_data(client_img)		# 再次接受响应的数据
    img_data = result_img.split(b'\r\n\r\n')[-1]
    # print(img_data)
	
    # 创建文件夹
    file_path = './images'
    os.makedirs(file_path, exist_ok=True)
    file_name = './images/{}.jpg'
    # 将图片数据写入文件
    with open(file_name.format(num + 1), 'wb')  as f:
        f.write(img_data)
        print('第%s张图片下载完成' % (num + 1))
# re.S 表示正则中的.(元字符)可以匹配换行符在内的所有字符(\r\n)

# makedirs 是超级的mkdir不用判断文件是否存在 直接指定参数exist_ok=True即可创建文件夹
图片下载思路:

1.先请求目标url

2.接收到该页面的数据(响应体); 从该页面匹配到所有的图片url (正则, xpath等)

3.循环对所有的url发起请求(多线程)

4.接收数据(构造数据)

5.写入文件

拓展

访问HTTPS 下载图片
import socket
import ssl


# 创建一个socket对象
sock = socket.socket()	

# ssl安全加成, 接收一个socket对象
client = ssl.wrap_socket(sock)  # wrap:意思就是将sock对象包起来 可以理解为数据从管道传输, 相比较http更加安全;所以说https传输的数据是加密的,就是基于该原理

# 然后再建立连接
client.connect(("117.157.234.247", 443))

....
# 后面步骤同http

 

补充: socket网络通信

import socket