python 爬虫(二)requests模块的介绍 + 基于requests模块的get请求和post请求 + 相关爬取案例(百度贴吧 + 百度产品 + 有道翻译 + 百度翻译)

一、requests模块


注意:
python模块的名字非常重要,一定要记住响应功能的导包语句。


1. requests模块的定义


requests模块是python中原生的基于网络请求的模块,其主要作用是用来模拟浏览器发起请求。功能强大,用法简洁高效。在爬虫领域中占据着半壁江山的地位。


2. 使用requests模块的原因


  • 因为在使用urllib模块的时候,会有诸多不便之处,总结如下:

    • 手动处理url编码
    • 手动处理post请求参数
    • 处理cookie和代理操作繁琐
  • 而使用requests模块

    • 自动处理url编码
    • 自动处理post请求参数
    • 简化cookie和代理操作

总结:

requests是基于python内置的urllib3来编写的,它比urllib更加方便,特别是在添加headers,post请求,以及cookies的设置上,处理代理请求,用几句话就可以实现,而urllib比较繁琐,requests比urllib方便多了,requests是一个简单易用的http请求库。


3. 如何使用requests模块


  • 安装(如果使用的是Anaconda编译器,便不用执行这一步):

    pip install requests
    
  • 使用流程
    ① 指定url
    ② 基于requests模块发起请求
    ③ 获取响应对象中的数据值
    ④ 持久化存储


二、基于requests模块的请求


1. requests模块get请求


① 完成请求的步骤


  1. 导包

    import requests
    
  2. 确定请求的url

    base_url = ''
    
  3. 发送请求,获取响应

    	response = requests.get(
    		url = base_url,#请求的url
    		headers={},请求头
    		params = {},请求参数字典
    	)
    

② response对象包含的内容


(1)状态码:

response.status_code

(2)响应头:

response.headers['Cookie']

(3)响应正文:

1.获取字符串类型的响应正文
	response.text
2.获取bytes类型的响应正文
	response.content
3.响应正文字符串编码
	response.encoding

(4)响应内容的乱码问题:

当我们用response.text获取字符串的响应正文的时候,有时候会出现乱码:

原因是response.encoding这个字段默认指定编码有误。

  • 解决办法
    第一种:

    手动指定
    response.encoding = ‘utf-8’
    

    第二种:

    	response.content.decode('utf-8')
    

③ get请求的项目类别三种情况


1. 没有请求参数的

比如百度和百度产品这两个项目,我们只需要添加请求头,封装user-agent这个请求头就可以了。

案例:
百度

##########爬取固定url无参数#################

## 1.导包
import requests
## 2. 确定url
base_url = 'http://www.baidu.com/'

## 封装请求头字典
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}

## 3. 发送请求,获取响应

# response = requests.get(base_url,headers=headers)
with requests.get(url=base_url,headers=headers) as response:
    if response.status_code == 200 :
        with open('baidu.html', 'w', encoding='utf-8') as fp:
            fp.write(response.content.decode('utf-8'))
    else:
        print(response.status_code)


## 查看页面内容
# print(response.text)

## fp = open('baidu.html','w',encoding='utf-8')
# with open('baidu.html','w',encoding='utf-8') as fp:
#     fp.write(response.content.decode('utf-8'))

百度产品

## 1.导包
import requests
## 2. 确定url
base_url = 'http://www.baidu.com/more/'

## 3. 发送请求,获取响应

response = requests.get(base_url)

## 查看页面内容
# print(response.text)
# print(response.encoding)

## 解决乱码
response.encoding='utf-8'
# print(response.text)

print(response.status_code)
print(response.headers)
print(type(response.text))
print(type(response.content))



# with open('index.html','w',encoding='utf-8') as fp:
    ## 如果写了上面一种解决乱码
    # fp.write(response.text)
    ## 如果上面没解决乱码
    # fp.write(response.content.decode('utf-8'))

2. 带请求参数的

比如新浪新闻这个项目
基础url就是问号以前包括问号的内容。
设置请求参数字典:
params = {
字典的内容就是chrome里面query string params里面的内容
}

案例:新浪新闻

###########爬取带参数的get请求网页?name="zhanbgsan"###########
import requests
## 带参数的get请求,基础url就是?之前包括问号的内容
base_url = 'http://search.sina.com.cn/?'

## 先要设置hearders字典和params字典,再发请求
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}

key = '王者'
params = {
 'q': key,
'c': 'news',
'from': 'channel',
'ie': 'utf-8',
}

response = requests.get(base_url,headers=headers,params=params)

with open('sina.html','w',encoding='gbk') as fp:
    fp.write(response.content.decode('gbk'))


3. 分页—百度贴吧

方法:
	1.先找出分页的规律。一般是通过params参数中的其中一个参数来控制的。
	2.找到这个参数每一页的规律。
	3.用for循环来请求每一页的内容。

案例:百度贴吧

import requests,os

base_url = 'http://tieba.baidu.com/f?'

## headers和params字典
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'
}
kw = '双十一'
## 一个路径,这个路径所对应的内容就是最后面的那个名字
dirname = './tieba/'+kw
parent_dir = os.path.dirname(dirname)
if not os.path.exists(parent_dir):
    os.mkdir(parent_dir)
if not os.path.exists(dirname):
    os.mkdir(dirname)

for i in range(10):
    params = {
        'ie': 'utf - 8',
        'kw':kw,
        'pn': str(i*50)
    }
    response = requests.get(base_url,headers=headers,params=params)
    with open(dirname+'/双十一第%s页.html' %(i+1),'w',encoding='utf-8') as fp:
        fp.write(response.text)

封装成面向对象

import requests


class Fanyi_baidu():
    def __init__(self,kw):
        self.base_url = 'https://fanyi.baidu.com/sug'
        self.data = {
             'kw': kw
            }
        self.headers = {
    ## 百度没有反爬措施,所以不写也行
    'content-length': str(len(self.data)),
    'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'origin': 'https://fanyi.baidu.com',
    'referer': 'https://fanyi.baidu.com/',
    'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
    'x-requested-with': 'XMLHttpRequest',
}


    def result(self):
        response = requests.post(self.base_url,headers=self.headers,data=self.data)
        json_data = response.json()
        result = ''
        for data in json_data["data"]:
            result += data['v'] + '\n'
        return result

kw = input("请输入你要查询的英文单词:")
a = Fanyi_baidu(kw)
print(a.result())


④ 查看网页使用的是get请求还是post请求的方法


在这里插入图片描述
get请求的url
在这里插入图片描述


⑤ 请求载体身份标识的伪装


  • User-Agent:请求载体身份标识,通过浏览器发起的请求,请求载体为浏览器,则该请求的User-Agent为浏览器的身份标识,使用爬虫程序发起的请求,则该请求的载体为爬虫程序,则该请求的User-Agent为爬虫程序的身份标识。可以通过判断该值来获知该请求的载体究竟是基于哪款浏览器还是基于爬虫程序。

  • 反爬机制:某些门户网站会对访问该网站的请求中的User-Agent进行捕获和判断,如果该请求的UA为爬虫程序,则拒绝向该请求提供数据。

  • 反反爬策略:将爬虫程序的UA伪装成某一款浏览器的身份标识。


2. requests模块post请求


① 格式


response = request.post(
	url,

	headers = {},

	data = {},请求数据字典

)

② post请求得到响应内容json的两种处理方法


  • post请求一般得到的响应内容是json数据
  • 处理json数据用到的模块就是json模块
  • 获得的json数据本质就是一个json字符串

json两种处理方法

- json.dumps(python的list或dict)-------->(返回值)----->json字符串
- json.loads(json字符串)------->(返回值)------------>python的list或dict

response对象自带的json方法

  • response对象有一个方法response.json()--------->可以直接将获取到的json字符串转换成python的list或dict------->这个方法返回值就是python的list或dict
response.json() 可以直接将获取到的json字符串转换成python的list或dict

③ post请求实现案例


案例:百度翻译

import requests

## 确定url
base_url = 'https://fanyi.baidu.com/sug'

## 封装headers字典和data字典
kw = 'python'
data = {
 'kw': kw
}
headers = {
    ## 百度没有反爬措施,所以不写也行
    'content-length': str(len(data)),
    'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'origin': 'https://fanyi.baidu.com',
    'referer': 'https://fanyi.baidu.com/',
    'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
    'x-requested-with': 'XMLHttpRequest',
}

response = requests.post(base_url,headers=headers,data=data)

json_data = response.json()
print(response.json())

result = ''
for data in json_data["data"]:
    result += data['v'] + '\n'
print(result)

在这里插入图片描述
案例:有道翻译

import requests

base_url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

data = {
    'i': 'python',
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15722527593368',
    'sign': '6b72a0409791e6264fd9be055b2a752d',
    'ts': '1572252759336',
    'bv': 'd2685b66b612e42764cb7b20e19ecbe4',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}

headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Content-Length': '239',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=329725962.8668213; OUTFOX_SEARCH_USER_ID="[email protected]"; _ga=GA1.2.1184567758.1572184613; _gid=GA1.2.975310807.1572184613; JSESSIONID=aaa9OYhn0K6ouhYCiKr4w; ___rl__test__cookies=1572252759331',
'Host': 'fanyi.youdao.com',
'Origin': 'http://fanyi.youdao.com',
'Referer': 'http://fanyi.youdao.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
}

response = requests.post(base_url,headers=headers,data=data)

print(response.text)

发现问题:爬取完后,我们发现,我们无法修改关键词,只可以查询词汇为我们一开始输入的固定单词,因此,我们需要找到办法可以使查出所有词汇。一般这种情况,由于某些参数的随时变化,我们需要在有道上翻译多个词来对比参数有哪些不同

解决思路如下:

  • 处理post请求参数怎么解决换了参数就请求不到的问题

  • 思路

    • 对比。比对data字典哪些参数是不一样的
    • 想办法找到这些参数的生成原理

案例:有道翻译,完善后
在这里插入图片描述
知道是这三个参数不一样,因此我们需要破解这三个参数,找到这些参数的生成原理,

常见的参数存放位置:

  • js中动态生成参数
  • 前端页面(可能是隐藏的hidden标签,都是固定写死的)
  • 可以通过ajax获取一些参数

具体js文件为(注意:要先刷新页面)
在这里插入图片描述
经过查询此处为某个js代码中的参数
在这里插入图片描述
修改参数
在这里插入图片描述
完善后代码

import requests,hashlib,time,random

base_url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

def get_md5(value):
    md5 = hashlib.md5()
    md5.update(bytes(value,encoding='utf-8'))
    return md5.hexdigest()
value = 'python'
salt = str(int(time.time()*1000)) + str(random.randint(0,10))
sign = get_md5("fanyideskweb" + value + salt +  "n%A-rKaT5fb[Gy?;N5@Tj")
ts = str(int(time.time()*1000))


data = {
    'i': value,
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': salt,
    'sign': sign,
    'ts': ts,
    'bv': 'd2685b66b612e42764cb7b20e19ecbe4',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}

headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Content-Length': '239',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=329725962.8668213; OUTFOX_SEARCH_USER_ID="[email protected]"; _ga=GA1.2.1184567758.1572184613; _gid=GA1.2.975310807.1572184613; JSESSIONID=aaa9OYhn0K6ouhYCiKr4w; ___rl__test__cookies=1572252759331',
'Host': 'fanyi.youdao.com',
'Origin': 'http://fanyi.youdao.com',
'Referer': 'http://fanyi.youdao.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
}

response = requests.post(base_url,headers=headers,data=data)

print(response.text)

发布了107 篇原创文章 · 获赞 43 · 访问量 6151

猜你喜欢

转载自blog.csdn.net/langdei/article/details/102787104