96、requests高级用法、Response、解析json、http与https的区别、代理池、爬取视频网站

224 阅读6分钟

requests高级用法

自动携带cookie 的session对象

1.session对象(自动处理cookie的session对象)---->已经模拟登录上了一些网站---->单独把cookie 取出来
	-res.cookies
  -转成字典 res.cookies.get_dict()
    
2.使用session发送请求
  session=requests.session()
  res = session.post('http://www.aa7a.cn/user.php', data=data, headers=header)
  res1 = session.get('http://www.aa7a.cn/') #不需要携带cookie了

案例

import requests

header = {
    'Referer': 'http://www.aa7a.cn/user.php?&ref=http%3A%2F%2Fwww.aa7a.cn%2F',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}

data = {
    'username': '616564099@qq.com',
    'password': 'lqz123',
    'captcha': 'xxxx',
    'remember': 1,
    'ref': ' http://www.aa7a.cn/',
    'act': 'act_login'
}
session = requests.session()
res = session.post('http://www.aa7a.cn/user.php',data=data,headers=header)
cookie = res.cookies.get_dict()   # 转字典
print(type(cookie))  # <class 'dict'>
res1 = session.get('http://www.aa7a.cn/')
print('616564099@qq.com' in res1.text)  # True

响应response

响应对象

from requests.models import Response

class Response:
    """The :class:`Response <Response>` object, which contains a
    server's response to an HTTP request.
    """

    __attrs__ = [
        "_content",
        "status_code",
        "headers",
        "url",
        "history",
        "encoding",
        "reason",
        "cookies",
        "elapsed",
        "request",
    ]
    ...还有各种方法

解释

response = requests.get('http://www.aa7a.cn/')
print(response)  # <Response [200]>
print(type(response))  # <class 'requests.models.Response'>http的响应,就是response对象,所有http响应的东西,都在这个对象中
print(response.text)  #  响应体转成字符串,默认使用utf-8编码---->以后打印出来可能会乱码
print(response.content)  # #响应体的bytes格式
print(response.status_code)  # 200
print(response.headers) # 响应头
print(response.cookies)  # cookie
print(response.cookies.get_dict())  # cookie 转成字典
print(response.cookies.items()) #键值对的形式[(),()]
print(response.url)    # 请求地址http://www.aa7a.cn/
print(response.history)  # # 访问一个地址,如果重定向了,requests会自动重定向过去,放着之前没重定向之前的地址,列表
print(response.encoding)  #网页编码 gbk

response.close() # 关闭:
response.iter_content()  # 一点一点取,用来下载图片视频之类的

下载图片,视频到本地

res = requests.get('https://assets.nst.com.my/images/articles/jisoo1_1678148772.jpg')
with open('jisoo.jpg','wb')as f:
    f.write(res.content)

res1 = requests.get('https://video.pearvideo.com/mp4/adshort/20181121/cont-1479880-13267554_adpkg-ad_hd.mp4')
with open('视频.mp4','wb')as f:
    for line in res1.iter_content(chunk_size=1024):
        f.write(line)

编码问题

1.直接打印res.text字符串形式----->从网络过来是二进制---->转成字符串涉及到编码--->默认以utf-8--->现在会自动识别页面的编码,自动转成对应的
res.encoding='gbk' # 手动指定编码
print(res.text)

requests其他用法

超时设置

try:
    response = requests.get('https://www.baidu.com',timeout=0.0001)
    print(response)
except Exception as e:
    print('访问超时了')

异常处理

from requests.exceptions import *  # 可以查看requests.exceptions获取异常类型
try:
    r=requests.get('http://www.baidu.com',timeout=0.00001)
except ReadTimeout:
    print('===')
except RequestException:
    print('Error')
except Exception as e:
    print(e)

上传文件

import requests
files = {"myfile":open('jisoo.png','rb')}
response = requests.post('http://127.0.0.1:8000/upload/',files=files)
print(response.status_code)

django应用

def upload(request):
    file = request.FILES.get('myfile')
    with open(file.name, 'wb') as f:
        for line in file:
            f.write(line)
    return HttpResponse('文件上传成功')

认证登陆

import requests
r=requests.get('xxx',auth=('user','password'))
print(r.status_code)

解析json

返回的可能是html,也可能是json(前后端分离项目,返回数据json格式),转成字典直接用

res = requests.post('http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword',
                    data={
                    "cname": '',
                    'pid': '',
                    "keyword": "周浦",
                    "pageIndex": "1",
                    "pageSize": "10",
                    })
print(type(res.json()))  # <class 'dict'>
print(res.json())
# 在json.cn解析数据
for item in res.json()['Table1']:
    print('餐厅名字:%s,餐厅地址:%s'%(item['storeName'],item['addressDetail']))

http与https的区别

文档:zhuanlan.zhihu.com/p/561907474

HTTP(Hypertext Transfer Protocol)和HTTPS(Hypertext Transfer Protocol Secure)是用于在Web浏览器和服务器之间传输数据的两种协议。它们之间的主要区别在于安全性。
1.安全性:
	HTTP是不安全的协议,数据在传输过程中是明文的,容易受到窃听和篡改的威胁。
	HTTPS通过使用SSL(Secure Socket Layer)或TLS(Transport Layer Security)协议对通信进行加密和身份验证,确保传输的数据是加密的,从而提供更高的安全性。

2.端口号:
	HTTP使用的默认端口号是80,而HTTPS使用的默认端口号是443。这是因为HTTPS在HTTP的基础上增加了加密层,需要使用不同的端口来区分。

3.证书:
	HTTPS需要使用SSL证书来进行身份验证。网站必须通过受信任的证书颁发机构(CA)获取有效的SSL证书。这个证书包含了用于加密通信的公钥和其他相关信息。
	HTTP不需要证书,因此无法验证服务器的身份,也容易受到中间人攻击。

4.SEO(搜索引擎优化):
	搜索引擎(如谷歌)通常更喜欢使用HTTPS加密的网站。使用HTTPS可以提高网站在搜索引擎结果页面中的排名,并为访问者提供更好的用户体验。

总的来说,HTTPS相比HTTP提供了更高的安全性和数据保护。对于涉及敏感信息(如个人身份信息、信用卡号等)的网站,使用HTTPS是非常重要的。

使用代理

1.访问某些网站,频率过高,就会被封ip---->使用代理ip访问---->封的是代理ip
2.代理有免费和收费两种,公司会花钱买代理的

案例

proxies = {
    'http':'85.133.151.83:3128'
}
response = requests.get('https://www.baidu.com/',proxies=proxies)
print(response)  # <Response [200]>

代理池搭建

1.搭建一个代理池--->每次可以从池中随机取出一个代理--->发送请求
2.公司内部要用,会花钱买
3.咱们自己用,基于网上的开源软件,自己搭建

4.开源的代理池核心原理:
	github:https://github.com/jhao104/proxy_pool
	1.使用爬虫技术,爬取网上免费的代理
  2.爬完回来做验证,如果能用,存到redis中
  	1.启动调度程序,爬代理,验证,存到redis中
			python proxyPool.py schedule
	3.使用flask启动服务,对外开放了几个接口,向某个接口发请求,就能随机获取一个代理
    	启动webApi服务:
			python proxyPool.py server

5.搭建步骤:
	1.从git拉去开源代码
    	git clone https://github.com/jhao104/proxy_pool.git
	2.使用pycharm打开,创建虚拟环境
    	mkvirtualenv -p python3 pool
  3.安装依赖:pip install -r requirements.txt
	4.配置项目使用虚拟环境
  	"""
  	workon pool
  	选择解释器:Python 3.10 virtualenv at ~/.virtualenvs/pool ~/.virtualenvs/pool/bin/python
  	"""
	5.修改项目配置文件
    DB_CONN = 'redis://127.0.0.1:6379/2'
		HTTP_URL = "http://www.baidu.com"
		HTTPS_URL = "https://www.baidu.com"
        
	6.启动调度程序--->爬取网站,验证,存到redis
    	python proxyPool.py schedule
        
	8.启动web程序(flask写的)
    	python proxyPool.py server
    	ps:另开一个终端
        
	9.向http://127.0.0.1:5010/get/?type=http地址发送请求就可以随机获取代理ip 

django后端获取客户端的ip

1.将Django项目部署在云服务器上(压缩、上传)
	"""
	scp Desktop/spider_django01.zip root@47.111.10.23:~
	unzip spider_django01.zip
	"""
2.修改配置文件
	1.将:ALLOWED_HOSTS = ['*']
  2.将数据库删掉
3.设置阿里云服务器安全组
4.执行命令:python3.9 manage.py runserver 0.0.0.0:8080

import requests
res = requests.get('http://127.0.0.1:5010/get/?type=http').json()["proxy"]

proxies={
    'http':res,
}
print(proxies)
response = requests.get('http://47.111.10.23:8080/',proxies=proxies)
print(response.text)
print(response.status_code)

"""
{'http': '47.100.69.29:8888'}
你的IP是:47.100.69.29
200
"""
def api_test(request):
    print(1111)
    ip = request.META.get('REMOTE_ADDR')
    return HttpResponse('你的IP是:%s'%ip)

爬去某视频网站

爬取梨视频网站

分析:下一页网址请求
https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start=96&mrd=0.13504542305107603&filterIds=1784061,1784086,1784133,1784259,1684602,1457064,1459530,1461099,1456881,1455053,1463177,1461844,1456455,1464635,1462847,1684540,1468288,1455979,1453053,1447959,1460605,1460248,1455279,1464237

https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start=120&mrd=0.9014471618667477&filterIds=1459562,1453165,1455676,1447662,1467105,1462162,1463935,1031332,1456681,1463575,1380501,1467342,1684471,1458016,1438151,1453440,1439324,1462493,1462238,1461675,1455121,1783927,1783922,1783929
import requests
import re

# 分析网站后,进行爬取
res = requests.get('https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start=0')
# 1.res中的text有多个a连接标签,就是视频的连接
mp4_list = re.findall('<a href="(.*?)" class="vervideo-lilink actplay">',res.text)
# print(mp4_list)

# 点击a连接,跳转:https://www.pearvideo.com/video_1457553
for video_id in mp4_list:
    url = "https://www.pearvideo.com/"+video_id
    print(url)  # https://www.pearvideo.com/video_1479880,猜测这个连接有mp4
    res1 =requests.get(url)
    # print(res1.status_code)  # 没有mp4,当在更新页面,会发送https://www.pearvideo.com/videoStatus.jsp?contId=1479880&mrd=0.9367970028358106,当浏览器访问,显示文章已下线
    # 发现请求头有Referer:https://www.pearvideo.com/video_1479880
    header={'Referer':url}
    res2 = requests.get('https://www.pearvideo.com/videoStatus.jsp?contId=%s'%video_id.split('_')[-1],headers=header)
    print(res2.json())   # 返回了mp4地址
    print(res2.json()['videoInfo']['videos']['srcUrl'])   # 访问不了
    # 视频真正连接地址   https://video.pearvideo.com/mp4/adshort/20181121/cont-1479880-13267554_adpkg-ad_hd.mp4
    # 访问不了的连接地址 https://video.pearvideo.com/mp4/adshort/20181121/1688738305572-13267554_adpkg-ad_hd.mp4
    #
    fake_url = res2.json()['videoInfo']['videos']['srcUrl']
    real_url = fake_url.split('/')[-1].split('-')[0]
    print(real_url)
    real_url_end = fake_url.replace(real_url,'cont-%s'%video_id.split('_')[-1])
    print(real_url_end)
    """
    真的:https://video.pearvideo.com/mp4/adshort/20181023/cont-1461408-13107048_adpkg-ad_hd.mp4
    现在:https://video.pearvideo.com/mp4/adshort/20181023/cont-1461408-13107048_adpkg-ad_hd.mp4
    """
    get_mp4=requests.get(real_url_end)
    print(get_mp4)  # <Response [200]>
    break

最后爬视频,爬5页,使用多线程(线程池),使用代理

import requests
import re
def get_proxy():
    return requests.get("http://127.0.0.1:5010/get/?type=https").json()  # proxy = get_proxy().get("proxy")

def delete_proxy(proxy):
    requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy))  # | /delete | GET | 删除代理  |`?proxy=host:ip`|


# 开启线程,线程池
from concurrent.futures import ProcessPoolExecutor
import os
import time

pool = ProcessPoolExecutor(5)

def task(res,proxy):
    # print(res)
    mp4_list = re.findall('<a href="(.*?)" class="vervideo-lilink actplay">', res.text)
    for video_id in mp4_list:
        url = "https://www.pearvideo.com/" + video_id
        # print(url)  # https://www.pearvideo.com/video_1479880,猜测这个连接有mp4
        res1 = requests.get(url)
        header = {'Referer': url}
        res2 = requests.get('https://www.pearvideo.com/videoStatus.jsp?contId=%s' % video_id.split('_')[-1],
                            headers=header,proxies={"https": proxy})
        # print(res2.json())  # 返回了mp4地址
        # print(res2.json()['videoInfo']['videos']['srcUrl'])
        fake_url = res2.json()['videoInfo']['videos']['srcUrl']
        real_url = fake_url.split('/')[-1].split('-')[0]
        # print(real_url)
        real_url_end = fake_url.replace(real_url, 'cont-%s' % video_id.split('_')[-1])
        # print(real_url_end)
        get_mp4 = requests.get(real_url_end)
        print(get_mp4)  # <Response [200]>


if __name__ == '__main__':
    for i in range(5):
        proxy = get_proxy().get("proxy")

        print(proxy)
        res = requests.get('https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start=%s'%i,proxies={"https": proxy})
        pool.submit(task,res,proxy)# 往池子中提交任务(异步)