目录
一、User-Agent的扩展
当需求是在一秒钟内访问某一网站30次,即对网站发送30次请求时,如果我们使用的是同一个User-Agent(用户代理),网站极有可能识别出来我们的爬虫身份。
解决办法:发送30次请求,使用30个不同的User-Agent(用户代理)
1.手动构建User-Agent池,一个列表里面储存着很多User-Agent,使用时每次从中随机取一个
2.使用第三方库 fake-useragent
# 1.手动构建User-Agent池
user_agents = [
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
'Opera/8.0 (Windows NT 5.1; U; en)',
'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2 ',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0) ',
]
# 2.使用第三方库fake-useragent
from fake_useragent import FakeUserAgent
user_agent = FakeUserAgent().random
print(user_agent)
# Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36
二、url携带参数
百度主页的url:https://www.baidu.com/
问题:当我们手动输入关键字:中国时,关键字是怎么到达百度服务器的呢?
答:浏览器将关键词添加到url当中,通过url携带参数(路由之后?之后所有的内容就是参数)
rsv_t=1fd8Sv%252BUY77sx7lJm38fviXEYz0cyC8aQlH9vT6COtZGsuFp5uSc48KQJw&
通过观察,可以发现他们都是以键值对的方式存在,两个参数(两个键值对)之间用and &符号分开,我们只输入关键词:中国,为什么会有这么多参数呢?其实这些大部分都是虚假参数,这些类似障眼法的参数即使拿掉也没有关系
我们在浏览器的地址栏和浏览器的抓包工具中对于同一个网页,他们url中的 wd 的内容却不一样
虽然 wd 的内容不一样,但却是同一个网页没有区别,这是因为在在我们发送请求时,中国两个字变成了%E4%B8%AD%E5%9B%BD
我们通常叫 中国 这类 为明文,%E4%B8%AD%E5%9B%BD我们看不懂的这类为密文(即为一种加密操作)
我们在python中如何实现这种加密和解密呢?(了解即可)
from urllib.parse import quote, unquote
# 先定义个明文数据
data_1 = '中国' # 通过url编码,会变成一个怎样的密文?
# 明文转密文
data_2 = quote(data_1)
print(data_2) # %E4%B8%AD%E5%9B%BD 通过对比和网站中中国的密文一样
# 密文转明文
data_3 = unquote(data_2)
print(data_3) # 中国
三、url传参
第一种方式(直接在url里面携带参数):
# 导入发送网络请求的requests
import requests
from fake_useragent import FakeUserAgent
if __name__ == '__main__':
# 确认关键词
kw_ = input('请输入要搜索的关键词:')
# 1.确认目标的url(前面分析了起作用的只有wd参数,其他参数都没有用)
url_ = f'https://www.baidu.com/s?wd={kw_}&rsv_spt=1&rsv_iqid=0xde60aa8800150949&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&rsv_sug3=8&rsv_sug1=8&rsv_sug7=101&rsv_sug2=0&rsv_btype=i&prefixsug=%25E4%25B8%25AD%25E5%259B%25BD&rsp=4&inputT=1609&rsv_sug4=2189'
# 构造用户代理User-Agent
headers_ = {
'User-Agent': FakeUserAgent().random
}
# 2.发送网络请求,获取响应对象
response_ = requests.get(url_, headers=headers_)
data_ = response_.content
# 3.保存在本地
with open('关键词1.html', 'wb') as f:
f.write(data_)
第二种方式(发送请求时携带参数):
# 导入发送网络请求的requests
import requests
from fake_useragent import FakeUserAgent
if __name__ == '__main__':
# 确认关键词
kw_ = input('请输入要搜索的关键词:')
# 1.确认目标的url(前面分析了起作用的只有wd参数,其他参数都没有用,第二种方法是在发送请求时加入关键字,所以把url中的wd参数删除掉)
url_ = 'https://www.baidu.com/s?&rsv_spt=1&rsv_iqid=0xde60aa8800150949&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&rsv_sug3=8&rsv_sug1=8&rsv_sug7=101&rsv_sug2=0&rsv_btype=i&prefixsug=%25E4%25B8%25AD%25E5%259B%25BD&rsp=4&inputT=1609&rsv_sug4=2189'
# 构造用户代理User-Agent
headers_ = {
'User-Agent': FakeUserAgent().random
}
# 在发送请求时为url添加参数,先构建关键字的键值对
params_ = {'wd': kw_}
# 2.发送网络请求,获取响应对象
response_ = requests.get(url_, headers=headers_, params=params_)
data_ = response_.content
# 3.保存在本地
with open('关键词2.html', 'wb') as f:
f.write(data_)
四、网易云音乐小案例
音频:在浏览器中打开网易云音乐,找到自己喜欢的音乐(不能vip的音乐),鼠标右键点击检查,然后找到clear按钮点击清空数据包,点击播放,在network中找到对应的数据包。
音频的数据包一般在media中,但也有特殊情况。如果不在media中我们根据size的大小来判断是否为音频的数据包
检查自己找到的数据包是否正确:双击数据包的name,如果跳转到播放页面即为正确的音频文件的数据包
在找到正确的数据包后即可获得正确的url,此时我们就可以通过python对音频文件进行下载
# 导入发送网络请求的requests
import requests
from fake_useragent import FakeUserAgent
if __name__ == '__main__':
# 1.确认目标的url
url_ = 'https://m701.music.126.net/20210630211225/ce4b7f374598a629aa4dee55c19fcc5b/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/9568880860/458f/d4f3/a66b/d40708839c04bf828333511e42e8fdbe.m4a'
# 构造用户代理User-Agent
headers_ = {
'User-Agent': FakeUserAgent().random
}
# 2.发送网络请求,获取响应对象(因为音频为字节型数据,所以我们用content)
response_ = requests.get(url_, headers=headers_)
media_data = response_.content
# 3.保存在本地
with open('自我乍现.mp3', 'wb') as f:
f.write(media_data)
视频:在浏览器中打开网易云音乐,找到自己喜欢的mv,鼠标右键点击检查,选择network,然后点击播放,在network中找到对应的数据包。
视频的数据包一般也在media中,但也有特殊情况。如果不在media中我们根据size的大小来判断是否为视频的数据包
检查自己找到的数据包是否正确:双击数据包的name,如果跳转到播放页面即为正确的视频文件的数据包
在找到正确的数据包后即可获得正确的url,此时我们就可以通过python对视频文件进行下载
# 导入发送网络请求的requests
import requests
from fake_useragent import FakeUserAgent
if __name__ == '__main__':
# 1.确认目标的url
url_ = 'https://vodkgeyttp9c.vod.126.net/cloudmusic/wJmKz8at_3552079912_hd.mp4?ts=1625062148&rid=47115DC667964F5C42BDE925D7219E80&rl=3&rs=gFAHHwFshGwxqOimUbUVWFTZUxUaAOka&sign=9e9367bcf08bd4555b3a6f3bee11d15b&ext=NnR5gMvHcZNcbCz592mDGR%252FsB9I27u7YCHC6INEq1zd2cXGX83DoffU4tC0T3SjX5hlTXZ8JzFfOIzpLOqFuM2pSGjQN76XXCVGPljB5HlsbZQuctrdE7J7NaG8g5GloNWUa1N3kcBHMFOi0v95X%252FNICdN16saSM42N9hcFcqndEtWiAI0os4UjHd6oM7r8NHMDIr8j7e6hlh0Rp3Jbfr3zEzgIweM3ipTiPiVXJLDoB9kGlyH40uyB9JC8lQQ4SDK40lXbx6mZEXd%252BJNix37TToSJLMeUk9bhmdfx7Q76QfepYCCMLuPU%252BWnevIPBUb0u75wMajucEEZ%252BJOBhZexGNT2YDmZCLI%252F4HWYYPhilihL9I8%252B%252Fvm%252BcDWhr445cljUGfLHjDA6YuvRfCmHM5GnM9jnEYq%252FX3TLDSkEbYhLYrdwerPeQ3hrevFlg%252BTIWlTntk7bbMF2j44EVvBTDk%252BFjaIVf%252Bnb96pd7rda0OekNYGQ1NZ78PVPbCXVeSkERzTknhIJSdhZfgjNOibNXe3Y1x94KDp957x3qjqYiH0TYM%253D'
# 构造用户代理User-Agent
headers_ = {
'User-Agent': FakeUserAgent().random
}
# 2.发送网络请求,获取响应对象(因为视频为字节型数据,所以我们用content)
response_ = requests.get(url_, headers=headers_)
media_data = response_.content
# 3.保存在本地
with open('自我乍现.mp4', 'wb') as f:
f.write(media_data)
五、ffmpeg的使用
上面提到我们要下载的音乐不能是vip才能下载的音乐,那么就没有办法下载到这首歌了吗?
在这我们用一个另辟蹊径的办法:有部分vip音乐是有mv的,而他们的mv通常是普通用户也可以看的,所以我们可以通过提取mv中的音频达到下载vip音乐的目的
实现方法:1.保存视频文件时,将后缀改为MP3(缺点:和mp4文件一样大)
2.使用ffmpeg提取音频(只支持抽离m4a音频格式,比mp3品质高)
此处我们重点介绍ffmpeg
ffmpeg -i 'xxx.mp4' -vn -y -acodec copy 'xxx.m4a'
# 导入发送网络请求的requests
import requests
from fake_useragent import FakeUserAgent
import os
if __name__ == '__main__':
# 1.确认目标的url
url_ = 'https://vodkgeyttp9c.vod.126.net/cloudmusic/AwGNgqeW_3531985312_hd.mp4?ts=1625064086&rid=47115DC667964F5C42BDE925D7219E80&rl=3&rs=bddUuGkKcYpPWrRkhiAASBFLjfomYbkX&sign=e049043991b442f0d356b8771ad7777c&ext=NnR5gMvHcZNcbCz592mDGZPybAa0NHJd4Dptbry7LRd2ZLECWfh7t3JkOxgr9p8UMST0DmFiJNFipj%252BcOuTr3GzDIwgJ0hDMDDCKcPwcEv%252Bgu4y5Pl1QYtyNhvBKoPJuMlY5redhDkwDNGhZJYp3qq5PrYwFjNhe8b2Wxxo5s3i7jU7nFSe9TS6tQV1blKk76SkOxJtZdkgzTEwW3pn5ddvKXdzgunAqkJnZe0upAJtCPZvZbyMggxoXp7DmXtaytMaF7YKHIXALGZDrgT5FKoD9ry7CYLhyEZmbY0sl4JOLGQfxhNQx2Lw02XuTYIOTuqWMuWFALT8mH8805PLxDrhi4jpU%252BA6FjBcbLgue%252FVDLQosZs1G1s09%252BuyE4Ly4ITg4jbBqcexLPJIc%252B96GiC2r%252FNDzv8ELnZcLOJ%252FtPdT5swGSnyZBz6ciRUSTjH46jSulYPecUjfxu14TRcdpUgdUaQXAZq9eH3cIzm5VZbLEnCQJeoVu7BF54AFOX86tUA4yBB2zVkfqRKM9r78nFqw%253D%253D'
# 构造用户代理User-Agent
headers_ = {
'User-Agent': FakeUserAgent().random
}
# 2.发送网络请求,获取响应对象(因为视频为字节型数据,所以我们用content)
response_ = requests.get(url_, headers=headers_)
media_data = response_.content
# 3.保存(视频)在本地
with open('会不会.mp4', 'wb') as f:
f.write(media_data)
# 4.提取音频
os.system('ffmpeg -i "会不会.mp4" -vn -y -acodec copy "会不会.m4a"')
# 5.删除视频
# os.remove('会不会.mp4')
六、Post请求
我们在平常的爬虫中,get请求用的多,post请求用的少
区别:get请求是直接向服务器发送请求,获取响应数据;post请求时客户端先给服务端一些数据,然后再获取响应(一般:登录操作都是post请求,因为要给服务端提供账号以及密码,提交完账号密码之后,才能获取到响应的响应)
虽然get请求可以在url中携带信息,但不安全而且能携带的数据量小
post请求可以在form表单中携带大量的数据,而且安全
当我们在一个网站登陆,进入登陆后的网站时,我们用此时的url在浏览器和使用python的get请求进行访问会出现不同的结果。我们使用python的get请求进行访问会得到登陆界面,而使用浏览器访问会进入登陆后的界面。这是因为浏览器会自动保存并携带cookie,cookie里面会有登录信息,这样就会自动登录,而我们在python代码中没有加入cookie,所以没有登陆信息,就会进入登陆界面。
如果想要获取登陆后的页面,应该怎么做?
1.利用python代码,发送post请求模拟登陆(用的比较少)
寻找登陆的url极其困难,此处以人人网为例
import requests
from fake_useragent import FakeUserAgent
if __name__ == '__main__':
# 1.确认目标的url
url_ = 'http://www.renren.com/PLogin.do'
# 用户代理
headers_ = {
'User-Agent': FakeUserAgent().random
}
# post请求携带数据,form表单
data_ = {
'email': 'xxxxxxx', # 账号
'password': 'xxxxxxx' # 密码
}
# 2.发送post请求
response_ = requests.post(url_, headers=headers_, data=data_)
content_ = response_.content
# 3.保存
with open('renren.html','wb') as f:
f.write(content_)
2.拿到登陆后的Cookie,发送get请求(用的比较多)
import requests
from fake_useragent import FakeUserAgent
if __name__ == '__main__':
# 1.确认目标的url(登陆后的url)
url_ = 'xxxxxxxx'
# 用户代理
headers_ = {
'User-Agent': FakeUserAgent().random,
'Cookie': 'xxxxxx' # 在network中主页的信息中找
}
# 2.发送get请求
response_ = requests.get(url_, headers=headers_)
content_ = response_.content
# 3.保存
with open('renren.html', 'wb') as f:
f.write(content_)
七、Cookie的扩展
Cookie记录了客户端和服务端的交互记录,最主要的是有登录信息的记录,可以更好的模拟正常用户
我们使用的不同的User-Agent,但却使用携带有相同登录信息的Cookie肯定是不行的,此时就需要一个Cookie池
Cookie池:特别是记录了登陆信息的Cookie,每一个Cookie就代表了一个账号
1.买账号
2.注册不同的账号
当我们每次请求的User-Agent和Cookie都不相同的时候,服务端可能会发现这么多不同的用户的ip地址却相同,也会采取一定的反爬手段,所以我们还需要代理ip池
代理IP池:买
八、SSL认证
安全证书错误:您的连接不是私密链接(SSL证书缺失)
浏览器:下载安全证书即可
Python:会碰见SSL ERRO 即碰到了安全证书的问题 解决办法:绕过安全证书
import requests
from fake_useragent import FakeUserAgent
if __name__ == '__main__':
# 1.确认目标的url(登陆后的url)
url_ = 'xxxxxxxx'
# 用户代理
headers_ = {
'User-Agent': FakeUserAgent().random,
'Cookie': 'xxxxxx' # 在network中主页的信息中找
}
# 2.发送get请求
response_ = requests.get(url_, headers=headers_, verify=False)
content_ = response_.content
# 3.保存
with open('renren.html', 'wb') as f:
f.write(content_)
在发送get请求时加上:verify = False 的参数即可
九、代理IP
IP地址:精确的定位
IP地址:1.家里通网,有了一个路由器,有了一个IP,即公网IP
2.电脑插上路由器的网线,电脑也有了自己的个人IP
代理IP:正向代理,即我们找了个中间商(代理IP)去找服务器,即使查出来我们是爬虫身份,也只会封禁中间商(代理IP)
Ngix:反向代理,一个服务端承受量可能有限,不能承受过多的用户访问,Ngix为了负载均衡,起路由分发的作用。相当于开了饭馆开了连锁店,去哪家店吃的都是一样的东西。
代理IP又分为透明代理(服务器知道我们使用了代理IP,并且知道我们的真实IP),匿名代理(服务器能够检测到我们使用了代理IP,但不知道我们真实的IP),高匿代理(服务器既不能检测出我们使用了代理IP,也无法知道我们的真实IP)