欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

程序员文章站 2024-01-25 22:24:16
...

一、requests模块的使用步骤

# 1、导包
import requests
# 2、确定基础url
base_url = 'https://www.baidu.com/'
# 3、发送请求,获取响应
response = requests.get(base_url)
# 4、处理响应内容

二、requests中的get方法

requests.get(
    url = '请求url',
    headers = {}, # 请求头
    params = {}, # 请求参数,get方法中的请求参数拼接在url中
    timeout = 超时时长,
)

requests模块的get方法,返回一个response对象


1、response对象

服务器响应包含:状态行(协议,状态码)、响应头、空行、响应正文。

(1)响应正文

字符串格式:response.text
bytes类型:response.content

(2)状态码

response.status_code

(3)响应头

response.headers  --字典
# 获取响应头中的cookie
response.headers['cookie']

(4)响应正文的编码

response.encoding

# response.text获取到的字符串类型的响应正文,其实是通过下面的步骤获取的
response.encoding = response.content.decode()

(5)乱码问题的解决办法

产生的原因:编码和解码的编码格式不一致造成的。

str.encode()  # 将字符串解码成bytes类型
bytes.decode()  # 将bytes类型编码成字符串

第一种方法:

response.content.decode('页面正确的编码格式')

第二种方法:找到正确的编码,设置到 response.encoding

response.encoding = '正确的编码'
response.text ---> 正确的页面内容

2、get 方法举例

案例一:爬取百度首页

https://www.baidu.com/

# 1、导包
import requests
# 2、确定基础url
base_url = 'https://www.baidu.com/'
# 封装请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
# 3、发送请求,获取响应
response = requests.get(base_url,headers=headers)
# 解决乱码问题的第一种方法
# response.encoding = 'utf-8'
# 4、处理响应
with open('baidu.html','w',encoding='utf-8') as fp:
    # fp.write(response.text)
    # 解决乱码问题的第二种方法
    fp.write(response.content.decode('utf-8'))

案例二:爬取新浪新闻

输入 国产航母 ,分析检查返回的页面,如下图所示:

爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理


爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-1 返回的页面

请求的是:https://search.sina.com.cn/?q=%E5%9B%BD%E4%BA%A7%E8%88%AA%E6%AF%8D&c=news&from=channel&ie=utf-8

请求方法是:get请求。

请求参数:有四个,其中一个参数是中文,请求的时候需要编码。

爬取代码示例:

# get请求,携带请求参数

# 1、导包
import requests
# 2、确定基础url
# 带请求参数的基础url,就是?以前包括问号
base_url = 'https://search.sina.com.cn/?'
# 封装请求头
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
# 请求参数
kw = '国产航母'
params = {
    'q': kw,
    'c': 'news',
    'from': 'channel',
    'ie': 'utf-8'
}
# 3、发送请求,获取响应
response = requests.get(base_url,headers=headers,params=params)
# 4、处理响应
# 右击-->检查  查看页面源代码
# <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
with open('sina_new.html','w',encoding='gbk') as fp:
    fp.write(response.content.decode('gbk'))

案例三:爬取百度贴吧

百度贴吧,搜索 python,利用get方法做分页

第一页:https://tieba.baidu.com/f?kw=%E7%8E%8B%E8%80%85&ie=utf-8&pn=0

第二页:https://tieba.baidu.com/f?kw=%E7%8E%8B%E8%80%85&ie=utf-8&pn=50

第三页:https://tieba.baidu.com/f?kw=%E7%8E%8B%E8%80%85&ie=utf-8&pn=100

寻找每个页面url中不同的地方,就是url最后的pn值不同

爬取代码示例:

# get方法 如何做分页
# 1、导包
import requests
import os

# 2、确定基础url
base_url = 'http://tieba.baidu.com/f?'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
kw = '王者吧'
filename = './tieba/' + kw
dirname = os.path.dirname(filename)
# print(dirname)
# 不存在就创建文件夹
if not os.path.exists(dirname):
    os.mkdir(dirname)
    if not os.path.exists(filename):
        os.mkdir(filename)
# 分页
for i in range(10):
    params = {
        'kw': kw,
        'ie': 'utf-8',
        'pn': str(i * 50),
    }
    # 3、发送请求,获取响应
    response = requests.get(base_url,headers=headers,params=params)
    # 4、处理响应
    with open(filename + '/{}.html'.format(i + 1),'w',encoding='utf-8') as fp:
        fp.write(response.text)

案例四:爬取百度搜索

百度首页,输入 python爬虫,爬取返回的页面

爬取代码示例:

# 1、导包
import requests

# 2、确定基础url
base_url = 'https://www.baidu.com/s?'
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
}
kw = 'python爬虫'
# 请求参数
params = {
    'wd': kw,
    'rsv_spt': '1',
    'rsv_iqid': '0xe2c14bcf0009669a',
    'issp': '1',
    'f': '8',
    'rsv_bp': '1',
    'rsv_idx': '2',
    'ie': 'utf-8',
    'tn': 'baiduhome_pg',
    'rsv_enter': '1',
    'rsv_dl': 'tb',
    'rsv_sug3': '15',
    'rsv_sug1': '9',
    'rsv_sug7': '100',
    'rsv_sug2': '0',
    'inputT': '4062',
    'rsv_sug4': '4672',
}

# 3、发送请求,获取响应
response = requests.get(base_url,headers=headers,params=params)
# 4、处理响应
with open('{}.html'.format(kw),'w',encoding='utf-8') as fp:
    fp.write(response.content.decode('utf-8'))

3、get请求总结

  1. 没有请求参数的情况下,只需要确定url和headers请求头。
  2. 有请求参数的情况下,右击–检查,找 query_string_params ,将里面的参数封装在params中。
  3. 分页主要是查看每页中,请求参数页码字段的变化,找到变化规律,用for循环就可以做到分页。

三、requests中的post方法

response = requests.post(
    url = '基础url',
    headers = {}, # 请求头
    data = {}, # 请求数据,post请求的请求数据放在请求实体中
    timeout = 超时时长,
)

requests模块的post方法,返回一个response对象.。

post请求一般返回数据都是json数据。

1、如何解析json数据

第一种方法:

  用response对象的json()方法,返回的是json字符串所对应的python的list或者dict

response.json() # 返回python的list或者dict

第二种方法:用json模块。

json.loads(json字符串) # 返回python的list或者dict
json.dumps(python的list或者dict) # 返回json字符串

2、post方法举例

案例一:重写百度翻译

  1. 浏览器打开:fanyi.baidu.com
  2. F12—Network
  3. 输入job(在输入过程中会不断请求服务器),例如输入"j"时请求,输入"jo"时请求,输入"job"时也在请求。
  4. 同时获取请求。

爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-2 服务器请求

url:https://fanyi.baidu.com/sug

请求方式:POST

请求数据:job

代码示例:

# 1、导包
import requests,json
# 2、基础url
base_url = 'https://fanyi.baidu.com/sug'
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
    'x-requested-with': 'XMLHttpRequest'
}
kw = 'job'
data = {
    'kw': kw
}
# 3、发送请求,获取响应
response = requests.post(base_url,headers=headers,data=data)
# print(response.text)  # json字符串
# print(response.json(),type(response.json()))
# 解析json的第一种方法
# json_data = response.json()
# 解析json的第二种方法 ---用json模块
json_data = json.loads(response.text)
result = ''
for data in json_data['data']:
    result += data['v'] + '\n'
print(result)

案例二:浅尝有道词典翻译

有道翻译网址:http://fanyi.youdao.com/

在翻译中输入python

爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-3 分析接口与请求方式

找到接口和请求的方式,如图 2-3 :

爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-4 参数类型为Form Data

代码实现:

import requests

base_url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
    'Content-Length': '239',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=515894077.54851353; OUTFOX_SEARCH_USER_ID="aaa@qq.com"; _ga=GA1.2.948183379.1577080175; JSESSIONID=aaadp5J-1dw47eLlC60-w; ___rl__test__cookies=1580365311867',
    'Referer': 'http://fanyi.youdao.com/'
}
kw = 'work'
data = {
    'i': kw,
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15803653118740',
    'sign': '8ec9fd2c8fe99a4f6969753839f60e5a',
    'ts': '1580365311874',
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}
response = requests.post(base_url,headers=headers,data=data)
print(response.text)
运行结果:
{"errorCode":50}

Process finished with exit code 0

我们发现,当 kw='python' 时,能够获取到翻译的结果;当我们改变 kw的值时,上述代码并不能获取到翻译的结果。

案例三:深入有道词典

那么怎么解决上个案例中的问题呢?

Form Data 中的参数中,我们看到 salt,sign,ts,这是添加数字签名的标记。也就是这三个参数的值是生成出来的,也就是说随着翻译内容的不同,这三个值可能是会变化的。像这种动态生成的值一般会写在js脚本文件中。

(1)查找对应的js文件,如图 2-5 :

爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-5 对应的js文件

(2)查看这个文件

复制Response中的内容,打开在线格式化代码,复制格式化之后的js代码,如图 2-6:
爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-6 查看js文件内容

为了方便查看,我们在新建一个js文件,并且搜索与salt等变化的参数相关的字符,如图 2-7 所示:
爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-7 找到相关内容

(3)生成 salt 内容

其中 (new Date).getTime() 这行语句我们可以在浏览器中的控制台上输出看一下,如图 2-8 :
爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-8 验证内容

可见是精确到毫秒的时间戳,(用同样的方式验证:parseInt(10 * Math.random(), 10)),我们可以在 python输出一个时间,两者做个对比
爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理

图 2-9 验证对比值

js中时间戳是以毫秒计算的,而python中的时间戳是以秒计算的。

所以在这个JS中生成的 salt 值
爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理
在python中可以这样生成:

import time
import random

salt = str(time.time()*1000 + random.randint(0,10))

(4)生成 ts 内容

JS 中生成的 ts:

ts = "" + (new Date).getTime()

python 中生成的 ts :

ts = str(time.time()*1000)

(5)生成 sign 内容
爬虫(二)requests模块---requests的基本使用,requests中的get和post方法详解,代理的基本原理
JS 中生成的 sign 值:

sign = n.md5("fanyideskweb" + kw + salt + "n%A-rKaT5fb[Gy?;aaa@qq.com")

python 中生成的 sign 值:

def get_md5(value):
    md5 = hashlib.md5()
    md5.update(value.encode('utf-8'))
    result = md5.hexdigest()
    return result
value = "fanyideskweb" + kw + salt + "n%A-rKaT5fb[Gy?;aaa@qq.com"
sign = get_md5(value)

代码实现:

# 有道翻译

import hashlib
import json
import random
import time

import requests

base_url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
    'Content-Length': '239',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=515894077.54851353; OUTFOX_SEARCH_USER_ID="aaa@qq.com"; _ga=GA1.2.948183379.1577080175; JSESSIONID=aaadp5J-1dw47eLlC60-w; ___rl__test__cookies=1580365311867',
    'Referer': 'http://fanyi.youdao.com/'
}

kw = 'work'
salt = str(time.time()*1000 + random.randint(0,10))
ts = str(time.time()*1000)
def get_md5(value):
    md5 = hashlib.md5()
    md5.update(value.encode('utf-8'))
    result = md5.hexdigest()
    return result
value = "fanyideskweb" + kw + salt + "n%A-rKaT5fb[Gy?;aaa@qq.com"
sign = get_md5(value)
data = {
    'i': kw,
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': salt,
    'sign': sign,
    'ts': ts,
    'bv': '42160534cfa82a6884077598362bbc9d',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}
response = requests.post(base_url,headers=headers,data=data)
# print(response.text)
# 解析json数据
json_data = json.loads(response.text) # 字典类型
result = ''
# 提取翻译后的结果
for data in json_data['smartResult']['entries']:
    result += data
print(result)

运行结果:
n. 工作;功;产品;操作;职业;行为;事业;工厂;著作;文学、音乐或艺术作品
vt. 使工作;操作;经营;使缓慢前进
vi. 工作;运作;起作用

Process finished with exit code 0

3、post 方法总结

post 请求能否成功,关键看请求参数。

如何查找是那个请求参数在影响数据获取?

通过对比,找到变化的参数。

找到参数的生成方式,就是解决这个 ajax 请求数据获取的途径。

寻找的办法有以下几种:

  1. 写死在页面。
  2. 写在 js 中
  3. 请求参数是在之前的一条 ajax 请求的数据里面提前获取好的。

四、代理

1、代理的基本原理

代理形象的说,他是网络信息的中转站。实际上就是在本机和服务器之间架了一座桥。

2、代理的作用

  • 突破自身 ip访问限制,访问一些平时不能访问的站点。
  • 访问一些单位或团体内部资源。
  • 提高访问速度。代理服务器的主要作用就是中转,所以一般代理服务器里面都是用内存来进行数据存储的。
  • 隐藏 ip。对于爬虫来说,我们用代理就是为了隐藏自身 IP,防止自身的 IP被*。

3、代理的分类

代理分类时,既可以根据协议区分,也可以根据其匿名程度区分。

  1. 根据协议区分
    1. FTP代理服务器:一般有上传、下载以及缓存功能,端口一般为 21、2121。
    2. HTTP代理服务器:主要用于访问网页,一般有内容过滤和缓存功能,端口一般为 80,8080。
    3. SSL/TLS代理:主要用于访问加密网站,一般有SSL或TLS加密功能(最高支持 128 位加密强度),端口一般为 443。
    4. Telnet代理:主要用于 telnet远程控制(黑客入侵计算机时常用于隐藏身份),端口一般为 23。
  2. 根据匿名程度区分
    1. 高度匿名代理:数据包会原封不动转化,在服务端看来,就好像一个普通用户在访问,做到完全隐藏 IP。
    2. 普通匿名代理:数据包会做一些改动,服务器有可能找到原 IP。
    3. 透明代理:不但改动数据,还会告诉服务器,是哪个用户访问的。
    4. 间谍代理:指组织或者个人用于记录用户传输的数据,然后进行研究、监控等目的的代理。

4、在requests模块中设置代理

proxies = {
    '代理服务器的类型':'代理ip'
}
response = requests.get(proxies = proxies)

代理服务器的类型:http,https,ftp

代理 ip:http://ip:port


作业:

1、股吧信息爬取

url:http://guba.eastmoney.com/

要求:爬取10页内容,保存到 guba文件夹下

2、金山词霸

url:http://www.iciba.com/

相关标签: 爬虫