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)# 往池子中提交任务(异步)