网络爬虫靶场: spiderbuf.cn/list
为什么要学习requests,而不是urllib?
- requests的底层实现就是urllib
- requests简单易用
- requests能够自动帮助我们解压(gzip压缩的)网页内容
requests的作用:
作用:发送网络请求,返回相应数据
参考文档: www.w3cschool.cn/requests2/
requests中解决编码的方法:
response.content.decode()
response.content.decode('gbk')
response.text
response.encoding = 'utf-8'
response.text和response.content的区别:
response.text
- 类型:
str - 修改编码方式:
response.encoding = 'utf-8'
response.content
- 类型:
bytes - 修改编码方式:
response.content.decode('gbk')
发送简单的请求:
下载图片:
response = requests.get('https://c-ssl.duitang.com/uploads/blog/202110/05/20211005124837_80ffd.jpg')
with open('E:/Study/code/Python/图片爬取/胡桃.jpg','wb') as f:
try:
f.write(response.content)
print('下载成功')
except:
print('下载失败')
发送带header的请求:
为什么请求需要带上header?
模拟浏览器,欺骗服务器,获取和浏览器一致的内容
header的形式: 字典
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'}
requests.get(url,headers=headers)
发送带参数的请求:
参数的形式: 字典
kw = {'wd':'胡桃'}
response = requests.get('https://www.baidu.com',params=kw)
练习
import requests
class TieBaSpider:
def __init__(self, tieba_name):
self.tieba_name = tieba_name
self.url_temp = "https://tieba.baidu.com/f?ie=utf-8&kw=" + tieba_name + "&fr=search"
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0"
}
def get_url_list(self):
"""
构造 url 列表
:param url:
:return:
"""
# url_list = []
# for i in range(10):
# url_list.append(self.url_temp.format(i * 50))
# return url_list
return [self.url_temp.format(i * 50) for i in range(10)]
def parse_url(self, url):
"""
发送请求,获取响应
:param url:
:return:
"""
print(url)
response = requests.get(url, headers=self.headers)
response.encoding = "utf-8"
return response.text
def save_html(self, html_str, page_num):
"""
保存 html 页面
:param html_str:
:param page_num:
:return:
"""
file_path = "{}-第{}页.html".format(self.tieba_name, page_num)
with open("E:/Study/code/Python/HTML文件/" + file_path, 'w') as f:
try:
f.write(html_str)
print("保存成功")
except Exception as e:
print(e)
def run(self):
"""
实现主要逻辑
:return:
"""
# 1.构造url列表
url_list = self.get_url_list()
# 2. 遍历 发送请求获取响应
for url in url_list:
html_str = self.parse_url(url)
# 3.保存
page_num = url_list.index(url) + 1
self.save_html(html_str, page_num)
if __name__ == '__main__':
tieba_spider = TieBaSpider('胡桃')
tieba_spider.run()
Request深入
发送POST请求:
哪些地方我们会用到POST请求?
- 登录注册(post比get安全)
- 需要传输大文本的时候(POST请求对数据长度没有要求)
所以爬虫也需要在这两个地方模拟浏览器发送post请求
使用requests库的post方法,可以向服务器发送包含数据的HTTP POST请求。以下是关于如何使用requests.post方法的具体介绍:
-
基本用法
- 带数据的post:当需要向服务器提交表单数据时,可以使用data参数。例如,在登录操作中,通常需要提交用户名和密码,这时可以将它们作为一个字典传递给data参数[^1^][^3^]。
- 带json的post:如果需要发送JSON格式的数据到服务器,可以使用json参数。这在与RESTful API交互时非常常见,因为JSON是一种轻量级的数据交换格式。
- 带header的post:可以通过headers参数自定义请求头信息。这在需要模拟浏览器行为或设置特定内容类型时非常有用。
- 带文件的post:如果要上传文件,可以使用files参数。这允许你指定要上传的文件路径,并将文件作为multipart/form-data发送给服务器。
-
高级用法
- 超时设置:通过timeout参数可以设置请求的最长等待时间,避免请求无限期地挂起[^2^]。
- 代理设置:如果需要通过代理服务器发送请求,可以通过proxies参数来设置代理服务器的地址和端口。
- 会话保持:使用Session对象可以在多次请求间保持会话状态,如cookies。这对于需要登录后才能访问的资源特别有用。
-
注意事项
- 安全性:在发送敏感信息(如密码)时,确保使用HTTPS协议,以防止数据在传输过程中被截获。
- 异常处理:应该捕获可能的异常,如连接错误、超时等,并适当处理这些异常。
使用代理: 问题:为什么爬⾍需要使⽤代理
- 让服务器以为不是同一个客户端在请求
- 防⽌我们的真实地址被泄露,防⽌被追究
proxies = {
'http':'8.220.204.215',
'https':'154.203.132.49',
}
requests.get('https://www.baidu.com',proxies=)
proxies的形式:字典
ip代理网站: www.kuaidaili.com/free/intr
使用代理IP 准备⼀堆的IP地址,组成IP池,随机选择⼀个IP来⽤
检查IP的可⽤性
- 可以使⽤requests检查
- 在线代理IP质量检查的⽹站
cookie和session区别
- cookie数据存放在客户端的浏览器上,session数据放在服务器上。
- cookie不是很安全,别⼈可以分析存放在本地的cookie并进⾏cookie欺骗
- session会在⼀定时间内保存在服务器上。当访问增多,会⽐较占⽤你服
- 务器的性能
- 单个cookie保存的数据不能超过4K,很多浏览器都限制⼀个站点最多保存 20个cookie
爬虫处理cookie和session
带上cookie、session的弊端:⼀套cookie和session往往和⼀个⽤户对应请求 太多,请求次数太多,容易被服务器识别为爬⾍
不需要cookie的时候尽量不去使⽤cookie
但是为了获取登录之后的⻚⾯,我们必须发送带有cookies的请求带上cookie、session的好处:能够请求到登录之后的⻚⾯
requests提供了⼀个叫做session类,来实现客户端和服务端的会话保持
使⽤⽅法
- 实例化⼀个session对象
- 让session发送get或者post请求
session = requests.sessions()
response = session.get('https://www.baidu.com',proxies=proxies)
请求登录之后的⽹站的思路
- 实例化session
- 先使⽤session发送请求,登录对应⽹站,把cookie保持在session中
- 在使⽤session请求登录之后才能访问的⽹站,session能够⾃动携带登录成功时保存在其中的cookie,进⾏请求
import requests
from urllib.parse import urljoin
session = requests.session()
post_url = 'https://login2.scrape.center/'
LOGIN_URL = urljoin(post_url, '/login')
INDEX_URL = urljoin(post_url, '/page/1')
post_data = {
'username': 'admin',
'password': 'admin'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
# session.post(post_url, data=post_data, headers=headers)
# r = session.get('https://login2.scrape.center/', headers=headers)
requests.post(LOGIN_URL, data=post_data, headers=headers)
response_index = requests.get(INDEX_URL)
print(response_index.status_code)
print(response_index.url)
print(response_index.text)
不发送post请求,使⽤cookie获取登录后的⻚⾯
- cookie过期时间很⻓的⽹站
- 在cookie过期之前能够拿到所有的数据,
- 配合其他程序⼀起使⽤,其他程序专⻔获取cookie,当前程序专⻔请求⻚⾯
requests小技巧
requests.utils.dict_from_cookiejar # 把cookie对象转化为字典
请求SSL证书验证
response = requests.get('https://www.12306.cn/mormhweb/',verify=False)
设置超时
response = requests.get(url,timeout=10)
配合状态码判断是否请求成功
assert response.status_code == 200
URL地址的编解码
requests.utils.unquote() 解码
requests.utils.quote() 编码