requests模块基础
版权声明:本博客来自路飞学城Python全栈开发培训课件,仅用于学习之用,严禁用于商业用途。
欢迎访问路飞学城官网:https://www.luffycity.com/
本节重点
- requests模块简介
- requests模块实战
1. requests模块简介
1.1 引子
-
在python实现的网络爬虫中,用于网络请求发送的模块有两种,第一种为urllib模块,第二种为requests模块。urllib模块是一种比较古老的模块,在使用的过程中较为繁琐和不便。当requests模块出现后,就快速的代替了urllib模块,因此,在我们课程中,推荐大家使用requests模块。
-
requests模块是python中原生的基于网络请求的模块,其主要作用是用来模拟浏览器发起请求。功能强大,用法简洁高效。在爬虫领域中占据着半壁江山的地位。
1.2 为什么用requests模块
- 在使用urllib模块的时候,会有诸多不便之处,总结如下:
- 手动处理url编码
- 手动处理post请求参数
- 处理cookie和代理操作繁琐
- ……
- 使用requests模块:
- 自动处理url编码
- 自动处理post请求参数
- 简化cookie和代理操作
- ……
1.3 如何使用requests模块
-
环境安装
- pip install requests
-
使用流程/编码流程
- 指定url
- UA伪装
- 请求参数的处理
- 基于requests模块发起请求
- 获取响应对象中的数据值
- 持久化存储
- 指定url
-
基本使用
需求:爬取搜狗首页的页面数据
import requests def get_sogou(): #step1 指定URL url = 'https://www.sogou.com/' #step2 发起请求 response = requests.get(url=url) #step3 获取响应数据,txt返回的是字符串形式的响应数据 page_txt = response.text print(page_txt) #step4 持久化存储 with open('./sogou.html','w',encoding='utf-8') as f: f.write(page_txt) print('爬虫结束-----') if __name__ == '__main__': get_sogou()
2. requests模块实战
2.1 实战之UA伪装
-
需求:爬取搜狗指定词条对应的搜索结果页面(简易网页采集器)
-
知识点:
- UA检测
- UA伪装
-
实例:
import requests #UA:User-Agent(请求载体的身份标识) #UA检测:门户网站的服务器会检测对应请求的载体身份标识,如果检测到请求的载体身份标识为某一款浏览器,说明 #该请求是一个正常的请求,但是,如果检测请求的载体身份标识不是基于某一款浏览器,则表示该请求为不正常的请求 #则服务器就很可能会拒绝该请求 #UA伪装:让爬虫对应的请求载体身份标识伪装成某一款浏览器 def get_sogou(): #UA伪装,将对应的User-Agent封装到一个字典中 headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } url = 'https://www.sogou.com/web' #处理url携带的参数:封装到字典中 kw = input('请输入要查询的字符:') param = { 'query':kw } response = requests.get(url=url,params=param,headers=headers) page_txt = response.text file_name = kw + '.html' with open(file_name,'w',encoding='utf-8') as f: f.write(page_txt) print('保存成功') if __name__ == '__main__': get_sogou()
2.2 实战之post请求及json响应
-
需求:破解百度翻译
-
知识点:
- post请求(携带了参数)
- 响应数据是一组json数据
-
实例:
import requests import json def get_baidu(): url = 'https://fanyi.baidu.com/sug' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } kw = input('请输入要翻译的字符') data = { 'kw':kw } response = requests.post(url=url,data=data,headers=headers) dic_obj = response.json() file = kw+'.json' f = open(file,'w',encoding='utf-8') json.dump(dic_obj,fp=f,ensure_ascii=False) print('翻译成功') if __name__ == '__main__': get_baidu()
补充知识点:
json.dumps 序列化时对中文默认使用的ascii编码,想输出真正的中文需要指定ensure_ascii=False。
2.3 实战之get请求参数设置
-
需求:爬取豆瓣电影分类排行榜htps://movie.douban.com/中的电影详情数据
-
知识点:
- params设置请求参数
-
实例:
import json import requests def get_douban(): url = 'https://movie.douban.com/j/chart/top_list' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } param = { 'type': '11', 'interval_id': '100:90', 'action':'', 'start': '0', 'limit': '20' } response = requests.get(url=url,params=param,headers=headers) list_data = response.json() f = open('./douban.json','w',encoding='utf-8') json.dump(list_data,fp=f,ensure_ascii=False) fp.close() print('爬取成功') if __name__ == '__main__': get_douban()
2.4 实战之post请求参数设置
-
需求:爬取肯德基餐厅查询http://www.kfc.comcn/kfccda/index.aspx中指定地点的餐厅数
-
知识点:
- post请求中params携带请求参数
-
实例:
import json import requests def get_kfc(): url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36' } data = { 'cname':'', 'pid':'', 'keyword': '深圳', 'pageIndex': '1', 'pageSize': '10' } params = { 'op':'keyword' } response = requests.post(url=url,headers=headers,data=data,params=params) result = response.json() total = result['Table'][0]['rowcount'] if total > 10: data['pageSize'] = total response = requests.post(url=url, headers=headers, data=data, params=params) result = response.json() f = open('./kfc.json','w',encoding='utf-8') json.dump(result,fp=f,ensure_ascii=False) print('爬取成功') if __name__ == '__main__': get_kfc()
2.5 实战之动态加载数据
-
需求:爬取国家药品监督管理总局中基于中华人民共和国化妆品生产许可证相关数据http://125.35.6.84:81/xk/(目前已无法访问,仅作思路参考)
-
知识点:
- 动态加载数据
- 首页中对应的企业信息数据是通过ajax动态请求到的
- 通过对以下详情页url的观察发现:
- url的域名都是一样的,只有携带的参数(id)不一样
- id值可以从首页对应的ajax请求到的json串中获取
详情页1:http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp?id=e6c1aa332b274282b04659a6ea30430a
详情页2:http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp?id=f63f61fe04684c46a016a45eac8754fe
- 详情页的企业详情数据也是动态加载出来的
- 所有的post请求的url都是一样的,只有参数id值是不同。
- 如果我们可以批量获取多家企业的id后,就可以将id和url形成一个完整的详情页对应详情数据的ajax请求的url。
企业信息1:http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById
企业信息2:http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById
-
实例(代码已无法运行,仅作思路参考):
import requests import json if __name__ == "__main__": headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36' } id_list = [] # 存储企业的id all_data_list = [] # 存储所有的企业详情数据 #批量获取不同企业的id值 url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList' #参数的封装 for page in range(1,6): page = str(page) data = { 'on': 'true', 'page': page, 'pageSize': '15', 'productName':'', 'conditionType': '1', 'applyname':'', 'applysn':'', } json_ids = requests.post(url=url,headers=headers,data=data).json() for dic in json_ids['list']: id_list.append(dic['ID']) #获取企业详情数据 post_url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById' for id in id_list: data = { 'id':id } detail_json = requests.post(url=post_url,headers=headers,data=data).json() # print(detail_json,'-------------ending-----------') all_data_list.append(detail_json) #持久化存储all_data_list fp = open('./allData.json','w',encoding='utf-8') json.dump(all_data_list,fp=fp,ensure_ascii=False) fp.close() print('over!!!')
2.6 实战之请求二进制数据
- 实例:
import requests
if __name__ == "__main__":
#如何爬取图片数据
url = 'https://pic.qiushibaike.com/system/pictures/12172/121721055/medium/9OSVY4ZSU4NN6T7V.jpg'
#content返回的是二进制形式的图片数据
# text(字符串) content(二进制)json() (对象)
img_data = requests.get(url=url).content
with open('./qiutu.jpg','wb') as fp:
fp.write(img_data)
2.6 实战之图片懒加载
-
需求:抓取站长素材http://sc.chinaz.com/中的图片数据
-
爬取初试:
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests from lxml import etree if __name__ == "__main__": url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', } #获取页面文本数据 response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' page_text = response.text #解析页面数据(获取页面中的图片链接) #创建etree对象 tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') #解析获取图片地址和图片的名称 for div in div_list: image_url = div.xpath('.//img/@src') image_name = div.xpath('.//img/@alt') print(image_url) #打印图片链接 print(image_name)#打印图片名称
运行结果观察发现,我们可以获取图片的名称,但是链接获取的为空,检查后发现xpath表达式也没有问题,究其原因出在了哪里呢?
-
图片懒加载概念:
图片懒加载是一种网页优化技术。图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间。为了解决这种问题,通过前后端配合,使图片仅在浏览器当前视窗内出现时才加载该图片,达到减少首屏图片请求数的技术就被称为“图片懒加载”。
网站一般如何实现图片懒加载技术呢?在网页源码中,在img标签中首先会使用一个“伪属性”(通常使用src2,original……)去存放真正的图片链接而并非是直接存放在src属性中。当图片出现到页面的可视化区域中,会动态将伪属性替换成src属性,完成图片的加载。
-
方案改进:
站长素材案例后续分析:通过细致观察页面的结构后发现,网页中图片的链接是存储在了src2这个伪属性中
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests from lxml import etree if __name__ == "__main__": url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', } #获取页面文本数据 response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' page_text = response.text #解析页面数据(获取页面中的图片链接) #创建etree对象 tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') #解析获取图片地址和图片的名称 for div in div_list: image_url = div.xpath('.//img/@src2') #src2伪属性 image_name = div.xpath('.//img/@alt') print(image_url) #打印图片链接 print(image_name)#打印图片名称