一木.溪桥学爬虫-03:请求模块urllib、 urllib.request、urllib.parse.urlencode、urllib.parse.quote(str)、.unquote()
一木.溪桥 在Logic Education跟Jerry学爬虫
07期:Python 爬虫
一木.溪桥学爬虫-03:请求模块urllib、 urllib.request、urllib.parse.urlencode、urllib.parse.quote(str)、parse.unquote()
日期:2021年1月26日
学习目标:
请求模块urllib
urllib.request
urllib.parse.urlencode
urllib.parse.quote(str)
parse.unquote()
urllib post 案例
学习内容:
爬虫请求模块
urllib
为什么学习 urllib?
- 有的一些比较老的爬虫项目用的是urllib
- 有时我们在做一些爬虫的时候往往需要requests + urllib 一起使用
- 是python内置的模块
- urllib在某些方面还是非常强大
urllib的快速入门
eg. 下载网上的一张图片
# 方法1--open, closeimport requestsurl = 'https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1603365312,' \'3218205429&fm=26&gp=0.jpg' req = requests.get(url) fn = open('code.png', 'wb') # 文件命名为code.png,wb 写入二进制数据 fn.write(req.content) # content中间存的是字节码(此处图片存储的就是二进制数据),而text中存的是Beautifulsoup根据猜测的编码方式将content内容编码成字符串。fn.close()
# 方法2--with open, 可以不用close()import requestsurl = 'https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1603365312,' \'3218205429&fm=26&gp=0.jpg' req = requests.get(url) with open('code2.png', 'wb') as file_obj:file_obj.write(req.content)
# 方法3-- 用python内置模块 urllib 中的 request 方法from urllib import requesturl = 'https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1603365312,' \'3218205429&fm=26&gp=0.jpg' request.urlretrieve(url, 'code3.jpg') # url网址,文件名code3.jpg
urllib.request 模块
版本
python2 :urllib2、urllib
python3 :把urllib和urllib2合并
常用的方法:
- urllib.request.urlopen(“网址”) 作用 :向网站发起一个请求并获取响应
- 字节流 = response.read()
- 字符串 = response.read().decode(“utf-8”)
- urllib.request.Request"网址",headers=“字典”) urlopen()不支持重构User-Agent
响应对象
- read() 读取服务器响应的内容
- getcode() 返回HTTP的响应码
- geturl() 返回实际数据的URL(防止重定向问题)
import urllib.requesturl = 'https://www.baidu.com/'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
} # User-Agent模拟浏览器# 1 创建请求对象urllib.request.Request() (构造user-agent 反反爬)
req = urllib.request.Request(url, headers=headers) # 2 获取响应对象urllib.request.urlopen()
res = urllib.request.urlopen(req)# 3 读取响应对象中内容 read().decode('utf-8') bytes --> str
html = res.read().decode('utf-8') # 拿到原始数据
print(html) # 打印原始数据
print(res.getcode()) # 返回状态码
print(res.geturl()) # 返回请求的网址(防止重定向问题)
**总结:**urllib.request用法
- 1 创建请求对象 urllib.request.Request() 构建user-agent
- 2 发起请求获取响应对象 urllib.request.urlopen()
- 3 读取响应对象的内容 read().decode(‘utf-8’) bytes --> str
常用方法
- urlencode(字典)
- quote(字符串) (这个里面的参数是个字符串)
- urllib.parse模块
请求方式
- GET 特点 :查询参数在URL地址中显示
- POST
- 在Request方法中添加data参数 urllib.request.Request(url,data=data,headers=headers)
- data :表单数据以bytes类型提交,不能是str
urllib.parse.urlencode
请求中有汉字的处理方法1~3
- 方法1:先urllib.parse.urlencode(dict字典) 转换成了%+十六进制,再去拼接。
import urllib.request
import urllib.parse
url = 'https://www.baidu.com/s?wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B'# wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B
url2 = 'https://www.baidu.com/s?wd=海贼王'
# 3个%是一个汉字
# 如果我请求的url地址中出现了中文字样,我们的思路就是把中文转换成%+十六进制的样式
# res = urllib.request.urlopen(url2) # 报错
# 第一种方式 urllib.parse.urlencode(dict字典) 转换成了%+十六进制
r = {'wd': '海贼王'} # 字典格式
result = urllib.parse.urlencode(r)
print(result) # wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B
print(type(result)) # <class 'str'># 拼接:
url3 = 'https://www.baidu.com/s?' + result
print(url3) # https://www.baidu.com/s?wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B
urllib.parse.quote(str)
方法2: urllib.parse.quote(str)
import urllib.request import urllib.parseurl = 'https://www.baidu.com/s?wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B'# %E6%B5%B7%E8%B4%BC%E7%8E%8B url2 = 'https://www.baidu.com/s?wd=海贼王'# 第二种方式 urllib.parse.quote(str) r = '海贼王' result = urllib.parse.quote(r) print(result) # %E6%B5%B7%E8%B4%BC%E7%8E%8B url4 = 'https://www.baidu.com/s?wd=' + result # 拼接: print(url4) # https://www.baidu.com/s?wd=%E6%B5%B7%E8%B4%BC%E7%8E%8B
url 里面的数据包含有 %+十六进制 parse.unquote()
下载王者荣耀壁纸
反爬的小细节
如果以后遇到了 url 里面的数据包含有 %+十六进制 这样的url我们是无法进行一个正常的请求,解决办法 通过 parse.unquote() 来进行处理
from urllib import parse from urllib import requestimg = parse.unquote('http%3A%2F%2Fshp%2Eqpic%2Ecn%2Fishow%2F2735012617%2F1611652313%5F84828260%5F14368%5FsProdImgNo%5F2%2Ejpg%2F200') print(img) # 转换后的图片地址, http://shp.qpic.cn/ishow/2735012617/1611652313_84828260_14368_sProdImgNo_2.jpg/200request.urlretrieve(img, 'code3.jpg') # 图片下载, img网址,文件名code3.jpg
练习1:在百度输入您要搜索的内容,例如:美女 结果保存成一个html文件
# 需求:在百度输入您要搜索的内容,例如:美女 结果保存成一个html文件import urllib.request import urllib.parseheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/87.0.4280.141 Safari/537.36' } # 常规的格式:https://www.baidu.com/s?wd=%E5%A6%B9%E5%AD%90key = input('请输入您要搜索的内容:') base_url = 'https://www.baidu.com/s?' wd = {'wd': key} result = urllib.parse.urlencode(wd) # 把中文转换成%+十六进制的样式 url = base_url + result # 拼接url # print(url) # 构建请求对象 req = urllib.request.Request(url, headers=headers) # 获取响应对象 res = urllib.request.urlopen(req) # 读取响应的数据 html = res.read().decode('utf-8') # 保存数据 with open('搜索.html', 'w', encoding='utf-8') as file_obj:file_obj.write(html)
练习2:爬取贴吧中想要的主题
# 爬取贴吧中想要的主题import urllib.request import urllib.parse # https://tieba.baidu.com/f?kw=%E5%AD%A6%E7%94%9F&pn=0 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/''87.0.4280.141 Safari/537.36' } # 贴吧的主题 name = input('请输入您要爬取的贴吧主题:') # 爬取的起始页和终止页 begin = int(input('请输入起始页:')) end = int(input('请输入终止页:')) # 对name进行处理 kw = {'kw': name} result = urllib.parse.urlencode(kw) # 拼接目标url kw=%E5%AD%A6%E7%94%9F 是要动态的去替换的 pn值 (page - 1) * 50 # range()函数的特点 range(5) range(0,5) range(0,5,1) list(range(5)) 0 1 2 3 4 for i in range(begin, end+1):pn = (i - 1) * 50base_url = 'https://tieba.baidu.com/f?'url = base_url + result + '&pn=' + str(pn)# 发起请求获得响应req = urllib.request.Request(url, headers=headers)res = urllib.request.urlopen(req)html = res.read().decode('utf-8')# 写入文件filename = '第' + str(i) + '页.html'with open(filename, 'w', encoding='utf-8') as f:print('正在爬取第%d页' %i)f.write(html)
RUN: 请输入您要爬取的贴吧主题:美女 请输入起始页:1 请输入终止页:3 正在爬取第1页 正在爬取第2页 正在爬取第3页
练习3:以函数形式,爬取贴吧中想要的主题
import urllib.request import urllib.parse # 读取页面def readPage(url):headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/''87.0.4280.141 Safari/537.36'}req = urllib.request.Request(url, headers=headers)res = urllib.request.urlopen(req)html = res.read().decode('utf-8')return html# 写入文件def writePage(filename, html):with open(filename, 'w', encoding='utf-8') as f:f.write(html)print('写入成功')# 主函数 1 调用前2个函数 2 其它的逻辑放到main()函数中def main():name = input('请输入您要爬取的贴吧主题:')begin = int(input('请输入起始页:'))end = int(input('请输入终止页:'))kw = {'kw': name}result = urllib.parse.urlencode(kw)for i in range(begin, end + 1):pn = (i - 1) * 50base_url = 'https://tieba.baidu.com/f?'url = base_url + result + '&pn=' + str(pn)# 调用函数html = readPage(url)filename = '第' + str(i) + '页.html'writePage(filename, html)if __name__ == '__main__':main()
RUN: 请输入您要爬取的贴吧主题:美女 请输入起始页:1 请输入终止页:4 写入成功 写入成功 写入成功 写入成功
练习4:以面向对象形式,爬取贴吧中想要的主题
import urllib.request
import urllib.parseclass BaiduSpider:def __init__(self):self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/''87.0.4280.141 Safari/537.36'}self.base_url = 'https://tieba.baidu.com/f?'def readPage(self, url):req = urllib.request.Request(url, headers=self.headers)res = urllib.request.urlopen(req)html = res.read().decode('utf-8')return htmldef writePage(self, filename, html):with open(filename, 'w', encoding='utf-8') as f:f.write(html)print('写入成功')def main(self):name = input('请输入您要爬取的贴吧主题:')begin = int(input('请输入起始页:'))end = int(input('请输入终止页:'))kw = {'kw': name}result = urllib.parse.urlencode(kw)for i in range(begin, end + 1):pn = (i - 1) * 50url = self.base_url + result + '&pn=' + str(pn)# 调用函数html = self.readPage(url)filename = '第' + str(i) + '页.html'self.writePage(filename, html)if __name__ == '__main__':spider = BaiduSpider()spider.main()
RUN:
请输入您要爬取的贴吧主题:美女
请输入起始页:1
请输入终止页:2
写入成功
写入成功
urllib post 案例
需求:
利用有道在线翻译,完成一个小翻译
向 url发起请求 当中需要携带数据 是我们要翻译的内容
Request Method: POST
Form data Post请求
import urllib.request
import urllib.parse
import json # json.loads()把json类型的字符串就可以转换成python类型的字典# 请输入您要翻译的内容
content = input('请输入您要翻译的内容:')# Form data 复制检查中Form data 中的全部数据
data = {'i': content, # 要翻译的内容'from': 'AUTO','to': 'AUTO','smartresult': 'dict','client': 'fanyideskweb','salt': '15880623642174','sign': 'c6c2e897040e6cbde00cd04589e71d4e','Its': '1588062364217','bv': '42160534cfa82a6884077598362bbc9d','doctype': 'json','version': '2.1','keyfrom': 'fanyi.web','action': 'FY_BY_CLICKBUTTION'
}
data = urllib.parse.urlencode(data)
# print(type(data)) str
data = bytes(data, 'utf-8') # 1.,str 转换为 bytes . 2.加encoding编码,TypeError: string argument without an encoding
# 目标url 去掉translate_o中的_o , 解决报错{"errorCode":50}的问题
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
}
req = urllib.request.Request(url, data=data, headers=headers)
res = urllib.request.urlopen(req)
html = res.read().decode('utf-8')
# print(html) # json类型的字符串
# 把json类型的字符串就可以转换成python类型的字典
r_dict = json.loads(html)
# 解析数据,取字典中的键translateResult的值[[{"src":"hello","tgt":"你好"}]]
r = r_dict['translateResult'] # [[{"src":"hello","tgt":"你好"}]]
# 取值列表中的列表中字典中的值
result = r[0][0]['tgt'] # [{"src":"hello","tgt":"你好"}] ->{"src":"hello","tgt":"你好"} -> "你好"
print(result)
'''{"type":"EN2ZH_CN","errorCode":0,"elapsedTime":1,"translateResult":[[{"src":"hello","tgt":"你好"}]]}'''
tips:
注意点一
data = urllib.parse.urlencode(data)
# print(type(data))
data = bytes(data,'utf-8') # TypeError: string argument without an encoding
注意点二
# 目标url 去掉_o
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
注意点三
r_dict = json.loads(html)
# 解析数据
r = r_dict['translateResult'] # [[{"src":"hello","tgt":"你好"}]]
result = r[0][0]['tgt'] # [{"src":"hello","tgt":"你好"}] ->{"src":"hello","tgt":"你好"} -> "你好"
print(result)
End !
Best wishes for you!
一木.溪桥学爬虫-03:请求模块urllib、 urllib.request、urllib.parse.urlencode、urllib.parse.quote(str)、.unquote()相关推荐
- 一木.溪桥学爬虫-04:requests模块
一木.溪桥 在Logic Education跟Jerry学爬虫 07期:Python 爬虫 一木.溪桥学爬虫-04:requests模块.cookie.session 日期:2021年1月31日 学习 ...
- 一木.溪桥学Python-14 异常捕获
一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-14:异常捕 ...
- 一木.溪桥学Python-03: Python 运算符
一木.溪桥 在Logic Education跟Amy学Python 12期:Python基础课 一木.溪桥学Python-03: Python 运算符 日期:2020年12月18日 学习目标: 算术. ...
- 一木.溪桥学Python-06:元组tuple、字典dict
一木.溪桥 在Logic Education跟Amy学Python 12期:Python基础课 一木.溪桥学Python-06:元组tuple.字典dict 日期:2020年12月25日 学习目标: ...
- python bar函数循环_一木.溪桥学Python-08: for循环、function函数
一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-08: fo ...
- 一木.溪桥学Python-10:函数闭包、装饰器、推导式
一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-10:函数闭 ...
- 一木.溪桥学Python-11:迭代器、生成器、面象对象class MyClass:、self 参数、 __init__() 方法、__str__() 方法
一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-11:迭代器 ...
- 一木.溪桥学Python-13:多继承、多态、常用魔法方法、单例模式
一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-13:多继承 ...
- 一木.溪桥学Python-04: Python基础数据类型int ,float ,bool ,complex,None,str, 转义字符
一木.溪桥 在Logic Education跟Amy学Python 12期:Python基础课 一木.溪桥学Python-04: Python基础数据类型int ,float ,bool ,compl ...
最新文章
- 一步一步搞定InfoPath(02)--配置VSTA
- AndroidStudio项目提交(更新)到github最详细步骤
- java 日期注解 xml_Spring xml注解+java注解
- Spring MVC入门示例教程--表单处理
- Sublime Text3前端必备插件
- 飞畅科技教你如何选择合适的交换机?
- 前端学习(982):jquery概述
- 阿里云安装Quantaxis
- 在c语言中定义共用型数据类型的关键字是,C语言的关键字共有32个,根据关键字的作用,可分其为数据类型关键...
- 12.Memcached 与 Redis 区别
- 解决ubuntu 用anaconda 安装R 语言后,无法安装R语言package的问题
- 台式机XP系统调节屏幕亮度
- JMeter入门教程
- idea修改注释模板
- 试图速成的RPG Maker MV 学习笔记(三)
- 使用ArcMap 生成TPK和geodatabase包
- 3、HeidiSQL数据库管理工具下载与安装
- HMI-66-【MeterDisplay for Arm Linux】液晶仪表Arm Linxu迁移
- 计算机检测不出移动硬盘,电脑不显示移动硬盘怎么办,检测不到移动硬盘的原因...
- Monitor的用法
热门文章
- 算法导论 实验三 快速排序及其优化
- 高效记忆/形象记忆(08)英语单词记忆-字母熟词拆分
- 昌吉学院计算机科学与技术专业,昌吉学院最好的专业是什么、哪些专业比较好...
- 解职场困惑不必东奔西走,Leo这里应有尽有(更新至09年8月31日)——Leo文章索引
- 最大似然估计到底是怎么一回事
- cw2vec: Learning Chinese Word Embeddings with Stroke n-gram Information
- android多国语言文件夹文件汇总
- linux 下php连接orical数据库
- Cloudfront HTTPS 性能优化
- 关于公交系统中运用NFC-TSM技术进行移动支付的解决