爬虫简介:
1.本质是:模拟发送http请求(request)--》解析返回数据(re,bs4, lxml,json)--》入库(redis, mysql,mongodb)
2.用app爬虫:本质一模一样
3.python做爬虫的优势:包多,有很多爬虫框架:scrapy:性能很高的爬虫框架,爬虫届的django
爬虫的应用:百度谷歌都是一个大爬虫,在百度搜索,其实就是去百度的服务器的库中搜的,百度会一直爬虫,在互联网上进行爬取,把页面存储到自己的库中
http协议:超文本传输协议,规定了浏览器与服务端之间数据传输的格式
四大特性:基于请求响应,基于tcp/ip作用于应用层之上的协议,无状态,无连接
数据格式:
请求格式:
请求首行:(请求方式 协议版本)
请求头:(一大堆的k,v键值对)
请求体:(携带的数据)
响应格式:
响应首行(响应状态码)
响应头(一大堆k,v键值对)
响应体 (浏览器展示给用户看的数据)
响应状态码:用数字来表示一大堆提示信息
1xx:服务端已经成功接收到客户端的数据正在处理
2xx:200表示请求成功 服务端已经返回了你想要的数据
3xx:重定向
4xx:404请求资源不存在,403是指当前不具备请求该资源的条件
5xx:500表示服务器错误
特点:
1)应用层协议
2)基于请求-响应模式:
客户端主动发起请求--》 服务端才能响应(服务端不能主动推送消息,所以做聊天室相关的要用轮询和长轮询,websocket协议:主动推送消息)
3)无状态保存(cookie,session,token)
4)无连接:一次请求一次响应(http协议的版本:0.9,1.1:多次请求,共用一个socket连接,2.0:一次请求,可以携带多个http请求)
http请求:请求首行,请求头,请求体
-127.0.0.1/name=god&age=18:放在请求首行
-post请求请求体中放数据:name=god&age=18 放在请求体中
-post请求,可以这样发:127.0.0.1/name=god&age=18,django数据requtes.GET
-放在体中的:request.POST
-请求体的格式(编码格式):
urlencode:name=god&age=18 ---》request.POST
json:{name:lqz,age:18} ---->request.POST取不出来(因为django框架没有做这个事)
formdata:传文件 ----》request.POST
http响应:
# 响应首行:状态码:1,2,3,4,5
# 响应头:key:value
-cookie:
-cache-control:缓存控制
# 响应体:
html,json
# 浏览器调试
-右键--》调试模式
-elements:响应体,html格式
-console:调试窗口(js输出的内容,在这能看到)
-network:发送的所有请求,all xhr:ajax请求
request模块
pip install request
以前是urlib2:内置的库,不太好用,繁琐,所以封装出request模块
# 1 request模块的基本使用
import requests
发送http请求
get,delete,post。。本质都是调用request函数
ret=requests.get('https://www.cnblogs.com')
print(ret.status_code) # 响应状态码
print(ret.text) # 响应体,转成了字符串
print(ret.content) # 响应体,二进制
ret=requests.post()
ret=requests.request("get",)
ret=requests.delete()
# 2 get 请求带参数
方式一:
ret = request.get('http://0.0.0.0:8001/name=xxx&age=18')
方式二:(推荐使用)中文会自动转码
ret=requests.get('http://0.0.0.0:8001/',params={'name':"美女",'age':18})
# 3 带headers
ret = request.get('http://0.0.0.0:8001/name=xxx&age=18',
headers={
#标志什么东西发出来的请求,携带浏览器信息,django框架,会从哪里取?(meta)
'User-Agent':'request',
# 上一个页面的地址,图片防盗链
'Referer':'xxx'
}
)
# 何为图片防盗链:如果图片的referer不是自己的网站,就会被直接禁掉
图片不能携带自定义的referer
# 4 带cookie,随机字符串(用户信息:也代表session),不管后台用的token认证,还是session认证
# 一旦登陆了,带着cookie发送请求,表示登陆了
# 第一种方式
# ret = requests.get('http://0.0.0.0:8001/?name=%E7%BE%8E%E5%A5%B3',
# headers={
# 'cookie': 'key3=value;key2=value',
# })
# 第二种方式
# ret = requests.get('http://0.0.0.0:8001/?name=%E7%BE%8E%E5%A5%B3',
# cookies={"islogin":"xxx"})
# print(ret)
# 5 发送post请求(注册,登陆),携带数据(body)
# psot方法携带的参数:data=None, json=None
# data:urlencoded编码
ret=requests.post('http://0.0.0.0:8001/',data={'name':"god",'age':18})
# json:json编码
import json
data=json.dumps({'name':"god",'age':18})
ret=requests.post('http://0.0.0.0:8001/',json=data)
print(ret)
# 注意:编码格式是请求头中带的,可以手动修改,在headers中改
# 6 session对象
session=requests.session()
跟requests.get/post用起来完全一样,但是它处理了cookie
# 假设是一个登陆,并且成功
session.post()
# 再向该网站发请求,就是登陆状态,不需要手动携带cookie,如果是request.get就需要手动带一个cookie
session.get("地址")
# 7 响应对象
print(respone.text) # 响应体转成str
print(respone.content) # 响应体二进制(图片,视频)
print(respone.status_code) # 响应状态码
print(respone.headers) # 响应头
print(respone.cookies) # 服务端返回的cookie
print(respone.cookies.get_dict()) # 转成字典
print(respone.cookies.items())
print(respone.url) # 当次请求的地址
print(respone.history) # 如果有重定向,放到一个列表中
print(respone.encoding) # 编码方式
response.iter_content() # 视频,图片迭代取值
with open("a.mp4",'wb') as f:
for line in response.iter_content():
f.write(line)
# 8 乱码问题
# 加载回来的页面,打印出来,乱码(我们用的是utf8编码),如果网站用gbk,
ret.encoding='gbk'
ret=requests.get('http://0.0.0.0:8001/user')
# ret.apparent_encoding当前页面的编码
ret.encoding=ret.apparent_encoding
# 9 解析json
# 返回数据,有可能是json格式,有可能是html格式
ret=requests.get('http://0.0.0.0:8001/')
print(type(ret.text))
print(ret.text)
a=ret.json()
print(a['name'])
print(type(a))
# 10 使用代理
# 正向代理
# django如何拿到客户端ip地址 META.get("REMOTE_ADDR")
ret=requests.get('http://0.0.0.0:8001/',proxies={'http':'地址'})
print(type(ret.text))
print(ret.text)
# 11 异常处理
# 用try except捕获一下 Exception
# 12 上传文件(爬虫用的比较少,后台写服务,)
# file={'myfile':open("1.txt",'rb')}
# ret=requests.post('http://0.0.0.0:8001/',files=file)
# print(ret.content)
代理
# 代理
有免费的代理,但是不够稳定
#使用代理有什么用?
drf:一分钟只能访问六次,限制ip
每次发请求的时候,random一下
代理池:列表
import requests
# ret=requests.get('https://www.cnblogs.com/',proxies={'http':'222.85.28.130:40505'})
# 高匿:服务器,不知道我是谁
# 普通:服务端是能够知道我的ip的
# http请求头中:X-Forwarded-For:代理的过程
# ret=requests.get('http://101.133.225.166:8080',proxies={'http':'222.85.28.130:40505'})
# ret=requests.get('http://101.133.225.166:8080',proxies={'http':'114.99.54.65:8118'})
# print(ret.text)