爬虫,requests高级用法,解析json,ssl认证,使用代理,超时设置,上传文件处理,代理池搭建,爬取某视频网站,爬取新闻

内容回顾

可变类型与不可变类型

可变类型:值发生改变,内存地址不变:列表,集合,字典

不可变类型:值发生改变,内存地址一定发生改变:字符串,整形,浮点型,布尔,元组

常用的魔法方法》某种情况下会自动触发

__init__()    在类加括号实例化对象时触发完成数据初始胡
__new__()	  在类加括号实例化对象时触发,创建出空对象,自动触发__init__()
__call__()    对象加括号
__getattr__()  对点一个不存在的属性触发
__setattr__()   对象.属性=值
__getattribute__()  对象点属性就会触发
__getitem__()  对象['属性'],属性不存在触发

__setitem__()  对象['属性']=值触发

上下文管理器:只要重写了__enter__ 和__exit__方法,就具备这个能力
with 对象 as  xx:
    写代码,触发__enter__的执行
写一行代码,触发exit做一些资源的清理工作
__str__ 在str对象或print对象时触发
__repr__ python解释器环境下,会默认显示对象的repr

魔法方法大全
https://www.cnblogs.com/liuqingzheng/articles/9949568.html

class Student:
     def __init__(self, name, age):
         self.name = name
         self.age = age
     def __repr__(self):
         return self.name
 
>>> s1 = Student('张三', 24)
>>> s1
张三

repr函数或交互式解释器调用的obj.__repr__()

如果str没有被定义,那么就会使用__repr来替代输出
__str__ __repr__  输出的都必须是字符串
__format__

按照设定的格式化代码进行格式化后输出


__del__

当对象在内存中被释放,自定触发执行,此方法一般无需定义,因为python是一门高级预先,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
__doc__

输出类中的注释

生成器是函数有yield关键字


只有__iter__ 是迭代器

__iter__  __next__ 是可迭代对象


拥有__len__支持len(obj)操作

拥有__hash__方法的对象支持hash(obj)操作

拥有__eq__ 方法对象支持相等的比较操作


类中的装饰

什么都不加是绑定给对象的,对象去调用会把自身当作第一个参数传进去,类去调会把类本身当做第一个参数传进去

classmethod绑定给类的方法

staticmethod相当于普通函数,无论是对象还是类调用有几个参数传几个参数

如何把方法包装成数据属性 property装饰饰器

类中隐藏属性或方法__开头,在python中其实并没有真正隐藏要调用使用_类名隐藏的属性例如:\_S1__\__age

双写一致性,数据库变化,redis没变,或redis变了,数据库没变,会导致数据不一致的情况

解决方案

修改数据,删除缓存  实时性高一些
修改数据,更新缓存,  
定时更新缓存,数据的实时性可能不太好

先删除缓存在写入数据

断点续传

分段传输,在上次基础上,把文件光标移动到上次传输数据后面,继续传输

内网穿透

https://zhuanlan.zhihu.com/p/370483324

缓存击穿

某个key值过期后,有大量请求,请求这个key值数据,会造成redis,同时大量请求数据库,给数据库造成巨大压力

爬虫

爬虫是什么

一个程序》模拟发送http请求》从网站app,小程序》获取数据》清洗数据》入库

爬虫的核心原理

发送http请求,解析数据

requests re

requests模块》大神》基于python内置模块urllib3》进行封装的

python界非常知名的库

模拟发送http请求:postman也是发送http请求的

python GUI

​ tkinter:内置模块

​ PyQI:python代码在qt平台写桌面应用

发送get请求,携带数据

request.get(地址,params=get请求的数据)

发送请求请求头

heaser={
    user-agent:
    cookies:
    referer

}
request.get(headers=heaser)

携带cookie 两种方式

直接放在请求头中:字符串 cookies:xx=dsads;ee=sasdfa

使用cookies参数requests.get(cookies={}/cookieJar)

使用session requests.session()

发送post请求

requests.post(url,data,json)

requests.session()>保持cookie以后不用手动携带,自动处理

响应对象

Response
	text
    content
    cookies
    headers
    encoding

编码问题

获取二进制数据

下载图片,视频

res.iter_content() 是一个可迭代对象

http请求头

referer:是http请求头中的一个数据,记录从哪个页面跳转过来的

图片防盗链

反扒image-20230316092620833

内容详细

requests高级用法

解析json

发送http请求,返回的数据会有xml格式也有json格式

import requests
data = {
    'cname': '',
    'pid': '',
    'keyword': '500',
    'pageIndex': 1,
    'pageSize': 10,
}
res = requests.post('http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword',data=data)
# print(res.text)  # json 格式字符串---》json.cn
print(type(res.json()))  # 转成对象  字典对象

ssl认证(了解)

http协议:明文传输

https协议:http + ssl /tsl

HTTP+SSL/TLS也就是在http上又加了一层处理加密信息的模块比http安全,可以防止数据在传输过程中被窃取,改变,确保数据的完整性

https://zhuanlan.zhihu.com/p/561907474

以后遇到证书提示错误问题ssl xx

不验证证书
import requests
respone=requests.get('https://www.12306.cn',verify=False) #不验证证书,报警告,返回200
print(respone.status_code)
关闭警告
import requests
from requests.packages import urllib3
urllib3.disable_warnings() #关闭警告
respone=requests.get('https://www.12306.cn',verify=False)
print(respone.status_code)
手动携带证书(了解)
import requests
respone=requests.get('https://www.12306.cn',
                     cert=('/path/server.crt',
                           '/path/key'))
print(respone.status_code)

使用代理(重要)

如果爬虫使用自身ip地址访问,很有可能被封ip地址,以后就访问不了了

我们可以使用代理ip

代理:收费和免费(不稳定)

res = requests.post('https://www.cnblogs.com',proxies={'http':'地址+端口'})
res = requests.post('https://www.cnblogs.com',proxies={'http':'27.79.236.66:4001'})

res = requests.post('https://www.cnblogs.com',proxies={'http':'60.167.91.34:33080'})
print(res.status_code)

高匿名代理和透明代理

高匿,服务器拿不到真实客户端的ip地址

透明:服务端能拿到真实客户端的ip地址后端如何拿到真正客户端ip地址

http请求头中有个 X-Forwarded-For:client,proxy1,proxy2

-x-forword-for 获得http请求端真实的ip地址

超时设置

import requests
respone=requests.get('https://www.baidu.com',timeout=1)

异常处理

import requests
from requests.exceptions import * #可以查看requests.exceptions获取异常类型

try:
    r=requests.get('http://www.baidu.com',timeout=0.00001)
except ReadTimeout:
    print('===:')
# except ConnectionError: #网络不通
#     print('-----')
# except Timeout:
#     print('aaaaa')

except RequestException:
    print('Error')

上传文件

# 3 上传文件
import requests
files = {'file': open('美女.png', 'rb')}
respone = requests.post('http://httpbin.org/post', files=files)
print(respone.status_code)

代理池搭建

requests发送请求使用代理

代理从那来公司花钱买

搭建免费的代理池

https://github.com/jhao104/proxy_pool

python:爬虫+flask写的

架构

image-20230316103529214

搭建步骤

git clone https://github.com/jhao104/proxy_pool.git

使用pycharm打开

安装依赖:pip install -r requirements.txt

修改配置文件(redis地址即可)

OST = "0.0.0.0"
PORT = 5010
DB_CONN = 'redis://127.0.0.1:6379/0'
PROXY_FETCHER #爬取哪些免费代理网站

启动爬虫程序

python proxyPool.py schedule

启动服务器端

python proxyPool.py server

随机使用一个免费代理

地址栏中输入:http://127.0.0.1:5010/get/

使用代码

import requests
from requests.packages import urllib3
urllib3.disable_warnings() #关闭警告
# 获取代理
res = requests.get('http://127.0.0.1:5010/get/').json()
proxies = {}
if res['https']:
    proxies['https'] = res['proxy']
else:
    proxies['http'] = res['proxy']
print(proxies)
res = requests.post('https://www.cnblogs.com', proxies=proxies,verify=False)
# res = requests.post('https://www.cnblogs.com')
print(res)

django后端获取客户端的ip

# 建立django后端---》index地址---》访问就返回访问者的ip


# django代码---》不要忘记改配置文件
# 路由
path('', index),
# 视图函数
def index(request):
    ip = request.META.get('REMOTE_ADDR')
    print('ip地址是', ip)
    return HttpResponse(ip)

测试端

import requests

from requests.packages import urllib3

urllib3.disable_warnings()  # 关闭警告

res = requests.get('http://127.0.0.1:5010/get/').json()

if res['https']:

    proxies = {
        'https': res['proxy']
    }
else:
    proxies = {
        'http': res['proxy']
    }

# proxies = {
#     'http':'27.79.236.66:4001'
# }
print(proxies)
# res2 = requests.get('http://test.ipw.cn', proxies=proxies,verify=False,timeout=1)
res2 = requests.get('http://101.43.19.239/get/', proxies=proxies,verify=False,timeout=1)
print(res2.headers)
print(res2.history)
print(res2.text)

爬取某视频网站

import requests
import re

res = requests.get('https://www.pearvideo.com/category_loading.jsp?reqType=5&categoryId=1&start=0')
# print(res.text)
# 解析出真正视频地址
video_list = re.findall('<a href="(.*?)" class="vervideo-lilink actplay">', res.text)
# print(video_list)
for i in video_list:
    # i='video_1212452'
    video_id = i.split('_')[-1]
    real_url = 'https://www.pearvideo.com/' + i
    # print('真正视频地址是:',real_url)
    headers = {
        'Referer': 'https://www.pearvideo.com/video_%s' % video_id
    }
    res1 = requests.get('https://www.pearvideo.com/videoStatus.jsp?contId=%s&mrd=0.29636538326105044' % video_id,
                        headers=headers).json()
    # print(res1["videoInfo"]['videos']['srcUrl'])
    mp4_url = res1["videoInfo"]['videos']['srcUrl']
    mp4_url = mp4_url.replace(mp4_url.split('/')[-1].split('-')[0], 'cont-%s' % video_id)
    print(mp4_url)
    res2 = requests.get(mp4_url)
    with open('./video/%s.mp4' % video_id, 'wb') as f:
        for line in res2.iter_content():
            f.write(line)

# headers={
#     'Referer': 'https://www.pearvideo.com/video_1212452'
# }
# res=requests.get('https://www.pearvideo.com/videoStatus.jsp?contId=1212452&mrd=0.29636538326105044',headers=headers)
#
# print(res.text)


# https://video.pearvideo.com/mp4/short/20171204/    1678938313577    -11212458-hd.mp4
# https://video.pearvideo.com/mp4/short/20171204/     cont-1212452    -11212458-hd.mp4

mp4_url = 'https://video.pearvideo.com/mp4/short/20171204/  1678938313577-11212458-hd.mp4'

爬取新闻

import requests
# pip install beautifulsoup4   解析xml的库
from bs4 import BeautifulSoup

res = requests.get('https://www.autohome.com.cn/all/1/#liststart')
# print(res.text)
# 第一个参数是要解析的文本 str
# 第二个参数是:解析的解析器  html.parser:内置解析器       lxml:第三方需要额外安装
soup = BeautifulSoup(res.text, 'html.parser')
# 查找所有类名叫article的ul标签   find_all
ul_list = soup.find_all(name='ul', class_='article')
for ul in ul_list:
    li_list = ul.find_all(name='li')
    # print(len(li_list))
    for li in li_list:
        h3 = li.find(name='h3')
        if h3:  # 不是广告
            title = h3.text
            url = 'https:' + li.find('a').attrs['href']
            desc = li.find('p').text
            img = li.find(name='img').attrs['src']
            print('''
            新闻标题:%s
            新闻连接:%s
            新闻摘要:%s
            新闻图片:%s
            ''' % (title, url, desc, img))


# 把所有图片下载到本地,把爬完的数据,存到mysql中---》pymysql---》commit

正向代理反向代理

https://www.cnblogs.com/liuqingzheng/p/10521675.html

正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端(买票的黄牛)

反向代理即服务端代理,代理服务端,客户端不知道实际提供服务的服务端(住房的代理)

img

posted @ 2023-03-16 18:35  clever-cat  阅读(39)  评论(0编辑  收藏  举报