request的使用1

1、概述

问题:为什么要学习requests,而不是urllib?
requests的底层实现就是urllib
requests简单易用
requests在python2 和python3中通用,方法完全一样
requests能够自动帮助我们解压(gzip压缩的等)网页内容

作用:发送网络请求,返回响应数据

中文文档 API:
http://docs.python-requests.org/zh_CN/latest/index.html

如何使用requests来发送网络请求?

2、request的基本使用

安装requests模块: pip install requests
使用步骤(三部曲):
导入模块: import reqeusts

  • 发送get请求,获取响应: response = requests.get(url)
  • 从响应中获取数据
  • 核心代码: 发送get请求

request的常用属性:

response.text 响应文本
respones.content 二进制形式的响应数据
response.status_code 响应状态吗
response.headers 响应头
response.request.headers 请求头

response.text 和response.content的区别

response.text
类型:str
解码类型: 根据HTTP头部对响应的编码作出有根据的推测,推测的文本编码
如何修改编码方式:response.encoding=”gbk”

response.content
类型:bytes
解码类型: 没有指定
如何修改编码方式:response.content.deocde(“utf8”)
更推荐使用response.content.deocde()的方式获取响应的html页面

实例1:爬取百度首页

 # 1. 导入这个模块; 如果没有就安装一下: pip install resquests
    import requests
    # 2. 发送请求(get)
    response = requests.get("http://www.baidu.com/")
    # 3. 读取数据
    # response.encoding = "utf8"
    # #print(response.encoding) #ISO-8859-1 拉丁文编码表; 希腊等一些欧洲国家
    #  text 属性: 返回 自动识别编码的字符穿, 如果要指定编码,可以使用encoding的属性来指定编码
    # content = response.text
    # print(content)
    # content 属性: 获取的是二进制数据,使用decode进行解码
    data = response.content.decode()
    print(data)
    # response.status_code  响应状态吗
    print(response.status_code)
    # response.request.headers  请求头
    print(response.request.headers)
    # response.headers   响应头
    print(response.headers)

解决乱码问题

先使用decode()来尝试解码, 现在国内80%网站都是用utf-8进行编码的
如果上面面没有解决乱码问题,就指定GBK的编码方式, 个别网站使用的是GBK
如果指定GBK还不行,就request的自动推断功能了,通过text 属性获取

    # 1. 现在国内80%网站都是用utf-8进行编码的
    data = response.content.decode()
    print(data)
    # 2. 如果上面面没有解决乱码问题,就指定GBK的编码方式
    # data = response.content.decode("GBK")
    # 3. 如果指定GBK还不行,就request的自动推断功能了,通过text 属性获取
    # data = response.text

练习2:下载图片

 # 1. 导入requests模块
    import requests
    # 2. 发送请求获取二进制数据(bytes)
    respone =  requests.get("http://imgsrc.baidu.com/image/c0%3Dpixel_huitu%2C0%2C0%2C294%2C40/sign=098c3f828cd6277ffd1f3a7841407a5c/3c6d55fbb2fb4316e3afd1432ba4462309f7d353.jpg")
    # 获取二进制数据; 注意: 这里不要解码, 因为图片,视频等文件都是二进制的不是文本,不需要解码
    # data = respone.content
    # 3. 把数据写入文件
    with open("壁纸.jpg", "wb") as f:
        f.write(respone.content)

requests带有请求头

我们直接发送请求获取到的baidu首页与真实不一样,该怎么办?
原因是百度的服务器认为,不是人给他发送请求.
默认使用requests模块发送请求: ‘User-Agent’: ‘python-requests/2.18.1’, 百度服务器就认为这是一个爬虫,就不给你真正的页面.
在requests发送请求指定headers的格式 requests.get(url, headers={})

为什么要发送带有请求头的请求呢? 就让服务器认为,这个是正常客户端请求. 从而给我真正的内容.
代码:

import requests

    # 定义请求头字典
    headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
    }

    # 发送请求,获取百度首页
    response = requests.get("http://www.baidu.com", headers=headers)
    # 那内容之前先判断一下状态

    print(response.request.headers)

    # print(response.status_code)
    if response.status_code == 200:
        print(response.content.decode())

使用requests模块发送带有参数的请求

练习3 如何模拟搜狗搜索内容 ?

发送带有参数请求,在URL后面加上query=要搜索的内容
URL编码:

https://www.sogou.com/web?query=%E9%9F%B3%E4%B9%90
在requests发送get请求指定参数的格式 ?

方式1: 自己拼接一个带有参数的URL
方式2: 在发送请求的时候,使用params进行指定格式:
requests.get(“url”, params={})

import requests
    # 发送带有参数的请求
    # 方式1: 拼接URL
    # 键盘录入要搜索的内容获取搜索结果
    # url = "https://www.sogou.com/web?query=%s"
    url = "https://www.sogou.com/web?query={}"
    key = input("请录入你要搜索的内容: ")
    # url = url % key
    url = url.format(key)
    # print(url)
    # 发送请求
    headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
    }
    response = requests.get(url,headers=headers)
    if response.status_code == 200:
        print(response.content.decode())

方式2: 使用字典指定请求参数

headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
    }
    # 准备参数
    key = input("请录入你要搜索的内容: ")
    params = {"query":key}

    basic_url = "https://www.sogou.com/web"
    # 发送带有参数的请求
    response = requests.get(basic_url, params=params, headers=headers)
    # 获取请求结果打印
    content = response.content.decode()
    print(content)

实例:爬取百度贴吧

实现任意贴吧的爬虫,保存网页到本地;

要求: 可以指定贴吧名称, 起始页与结束页
思路:

找出访问贴吧内容的URL的规律
http://tieba.baidu.com/f?kw=吧名&ie=utf-8&pn=(页码-1)*50
代码实现
根据规律生成访问贴吧内容页面的URL,放到列表中
遍历URL,发送请求,获取内容
把内容页面写到文件中

import requests

# 定义一个贴吧爬虫类
class TiebaCrawler(object):
    # 基础URL
    basic_url = "http://tieba.baidu.com/f?kw={}&ie=utf-8&pn={}"
#     初始化方法
    def __init__(self, name, start, end):
        self.name = name
        self.start = start
        self.end = end

    #  2.1  根据规律生成访问贴吧内容页面的URL,放到列表中
    def get_url_list(self):
        # 定义一个list
        # url_list = []
        # # 生成URL放入list中
        # for i in range(self.start, self.end+1):
        #     url = self.basic_url.format(self.name, (i-1)*50)
        #     url_list.append(url)
        #  #返回list的列表
        # return url_list
        # 扁平化写法: 推荐,简洁
        return [self.basic_url.format(self.name, (i-1)*50) for i in range(self.start, self.end+1)]

    # 写一个方法下载URL中内容
    def download_from_url(self, url):
        response = requests.get(url)
        return response.content

    # 写一个方法把内容写到文件中
    def write_to_file(self, filename, content):
        with open(filename, "wb") as f:
            f.write(content)

    # 下载方法,存储主逻辑
    def run(self):
        # 2.1  根据规律生成访问贴吧内容页面的URL,放到列表中
        url_list = self.get_url_list()
        # print(url_list)
        # 遍历URL,发送请求,获取内容
        for url in url_list:
           content = self.download_from_url(url)
           # 文件名称: 贴吧名称_页码
           file_name = "{}_第{}页.html".format(self.name, url_list.index(url)+1)
           # 把内容页面写到文件中
           self.write_to_file(file_name, content)
        print("写入完成")

if __name__ == '__main__':
    # 思路: 从用户角度去考虑代码写法
    # 你要下载那个贴吧内容创建一个对象,指定贴吧名称,起始页和结束页,调用run方法就可以了
    ts = TiebaCrawler("电影", 1, 5)
    ts.run()

3、使用requests模块发送post请求

请问我们注册和登录是发送get请求还是post请求为什么?
POST:
原因: 登陆是把账号和密码信息提交给服务器, POST更加安全
当我们发送的内容比较多的时候,是使用get请求还是post请求为什么
POST
原因: POST可以提交"大""数据
我们写爬虫的时候, 不可避免要发送POST请求, 使用requests模块如何发送POST请求呢?

使用requests模块发送POST请求格式

requests.get(url, params={}, headers={}) # get请求
requests.post(url, data={}, headers={}) # POST请求

演示: 向http://httpbin.org/post 发送一个POST请求, 测试数据是否能传递成功

说明: http://httpbin.org 是一个专门用于测试http请求网站

代码

import requests
# 表单数据
data = {
    'name': 'lao wang'
}
# 发送POST请求
response = requests.post("http://httpbin.org/post", data=data)

print(response.content.decode())

实例:模拟百度翻译

import json
import requests
url = 'https://fanyi.baidu.com/sug'
headers = {
        'Accept': 'application/json, ext/javascript, */*; q=0.01',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36 FS',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'X-Requested-With': 'XMLHttpRequest'
}
key = input("请输去你要翻译的文字")
data = {
    'kw':key
}
resp = requests.post(url=url,headers=headers,data=data)
a = json.loads(resp.content.decode('utf-8'))
print(a)

4、在requests模块中使用代理发送请求

什么是代理

代理概述

  • 玩爬虫为什么我们不能使用一个固定IP发送请求

你使用一个固定IP发送每秒向对方服务器发送10几个请求,对方认为这样操作不是人干的, 就把你IP给封了
服务器端的人可以根据你IP很快锁定你, 要求你对这种窃取行为赔偿.

  • 代理
    在这里插入图片描述

正向代理与反向代理

在这里插入图片描述
在这里插入图片描述
正向代理与反向代理的区别

  • 反向代理:
    • 服务器端知道代理的存在,反向代理是为了保护服务器或负责负载均衡
      但是客户端不知道代理的存在的
  • 正向代理:
    • 客户端知道代理的存在,正向代理是为保护客户端,防止追究责任.
      但是服务端不知道真实的客户端

代理IP的分类

根据代理ip的匿名程度,代理IP可以分为下面四类:

透明代理(Transparent Proxy):透明代理虽然可以直接“隐藏”你的IP地址,但是还是可以查到你是谁。
匿名代理(Anonymous Proxy):使用匿名代理,别人只能知道你用了代理,无法知道你是谁。

高匿代理(Elite proxy或High Anonymity Proxy):高匿代理让别人根本无法发现你是在用代理,所以是最好的选择。

在使用的使用,毫无疑问使用高匿代理效果最好

从请求使用的协议可以分为:

http代理
https代理
socket代理等
不同分类的代理,在使用的时候需要根据抓取网站的协议来选择

在requests模块中使用代理(重点)

在requests模块中使用代理格式(重点)

 proxies = {
      "http":"http://ip:端口号"
      "https":"https://ip:端口号"
   }
   request.get(url, proxies=proxies)

使用需要账号和密码的代理

   proxies = {
      "http":"http://username:password@ip:端口号"
      "https": "https://username:password@ip:端口号"
   }
   request.get(url, proxies=proxies)
实例
  import requests

      # 使用代理获取百度首页
      headers = {
          "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
      }
      #  定义代理的字典
      proxies = {
          # "http":"http://14.118.252.64:6666"
          # "https":"https://114.99.30.126:18118"
          "http": "http://121.228.8.93:8118"
      }

      # 使用代理给服务器发送请求
      response = requests.get("https://www.baidu.com", proxies=proxies, headers=headers)
      # 获取状态
      print(response.status_code)
      print(response.content.decode())

代理IP使用的注意点

反反爬

使用代理ip是非常必要的一种反反爬的方式

但是即使使用了代理ip,对方服务器任然会有很多的方式来检测我们是否是一个爬虫,比如:

一段时间内,检测IP访问的频率,访问太多频繁会屏蔽

检查Cookie,User-Agent,Referer等header参数,若没有则屏蔽

服务方购买所有代理提供商,加入到反爬虫数据库里,若检测是代理则屏蔽

所以更好的方式在使用代理ip的时候使用随机的方式进行选择使用,不要每次都用一个代理ip

代理ip池的更新

购买的代理ip很多时候大部分(超过60%)可能都没办法使用,这个时候就需要通过程序去检测哪些可用,把不能用的删除掉。

使用代理的好处:
让目标服务器以为不是同一个客户端在请求,防止因为同一个ip发送请求过多而被反爬
防止我们的真实地址被泄露,防止被追究,保护自己

随机代理案例

我们说使用代理的目标是为了避免同一个IP发送请求频率过高而被识别为爬虫对吧,我们上面演示中是不是还是使用一个IP; 那么我们在实际开发中是怎么玩的呢?

准备一个代理池, 使用的时候随机获取一个来用

思路:

准备一个代理的列表
从列表中随机取出一个代理
使用这个代理发送请求

  import random
    import requests
    # 1. 准备代理列表
    proxies = [
        {'http': '121.8.98.198:80'},
        {'http': '39.108.234.144:80'},
        {'http': '125.120.201.68:808'},
        {'http': '120.24.216.39:60443'},
        {'http': '121.8.98.198:80'},
        {'http': '121.8.98.198:80'}
    ]

    # 2. 随机选出一个代理
    for i in range(0, 10):
        proxy = random.choice(proxies)
        print(proxy)
        try:
            response = requests.get("http://www.baidu.com", proxies=proxy, timeout=3)
            print(response.status_code)
        except Exception as ex:
            print("代理有问题: %s" % proxy)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值