爬虫requests库

151 阅读5分钟

网络爬虫靶场: spiderbuf.cn/list

scrape.center/

为什么要学习requests,而不是urllib?

  1. requests的底层实现就是urllib
  2. requests简单易用
  3. 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')

发送简单的请求:

图片.png

下载图片:

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)

发送带参数的请求:

eg:www.baidu.com/s?wd=python

参数的形式: 字典

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请求?

  1. 登录注册(post比get安全)
  2. 需要传输大文本的时候(POST请求对数据长度没有要求)

所以爬虫也需要在这两个地方模拟浏览器发送post请求

使用requests库的post方法,可以向服务器发送包含数据的HTTP POST请求。以下是关于如何使用requests.post方法的具体介绍:

  1. 基本用法

    • 带数据的post:当需要向服务器提交表单数据时,可以使用data参数。例如,在登录操作中,通常需要提交用户名和密码,这时可以将它们作为一个字典传递给data参数[^1^][^3^]。
    • 带json的post:如果需要发送JSON格式的数据到服务器,可以使用json参数。这在与RESTful API交互时非常常见,因为JSON是一种轻量级的数据交换格式。
    • 带header的post:可以通过headers参数自定义请求头信息。这在需要模拟浏览器行为或设置特定内容类型时非常有用。
    • 带文件的post:如果要上传文件,可以使用files参数。这允许你指定要上传的文件路径,并将文件作为multipart/form-data发送给服务器。
  2. 高级用法

    • 超时设置:通过timeout参数可以设置请求的最长等待时间,避免请求无限期地挂起[^2^]。
    • 代理设置:如果需要通过代理服务器发送请求,可以通过proxies参数来设置代理服务器的地址和端口。
    • 会话保持:使用Session对象可以在多次请求间保持会话状态,如cookies。这对于需要登录后才能访问的资源特别有用。
  3. 注意事项

    • 安全性:在发送敏感信息(如密码)时,确保使用HTTPS协议,以防止数据在传输过程中被截获。
    • 异常处理:应该捕获可能的异常,如连接错误、超时等,并适当处理这些异常。

使用代理: 问题:为什么爬⾍需要使⽤代理

  1. 让服务器以为不是同一个客户端在请求
  2. 防⽌我们的真实地址被泄露,防⽌被追究

图片.png

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的可⽤性

  1. 可以使⽤requests检查
  2. 在线代理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类,来实现客户端和服务端的会话保持

使⽤⽅法

  1. 实例化⼀个session对象
  2. 让session发送get或者post请求
session = requests.sessions()  
response = session.get('https://www.baidu.com',proxies=proxies)

请求登录之后的⽹站的思路

  1. 实例化session
  2. 先使⽤session发送请求,登录对应⽹站,把cookie保持在session中
  3. 在使⽤session请求登录之后才能访问的⽹站,session能够⾃动携带登录成功时保存在其中的cookie,进⾏请求

登录 login2.scrape.center/

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() 编码