一木.溪桥 在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()相关推荐

  1. 一木.溪桥学爬虫-04:requests模块

    一木.溪桥 在Logic Education跟Jerry学爬虫 07期:Python 爬虫 一木.溪桥学爬虫-04:requests模块.cookie.session 日期:2021年1月31日 学习 ...

  2. 一木.溪桥学Python-14 异常捕获

    一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-14:异常捕 ...

  3. 一木.溪桥学Python-03: Python 运算符

    一木.溪桥 在Logic Education跟Amy学Python 12期:Python基础课 一木.溪桥学Python-03: Python 运算符 日期:2020年12月18日 学习目标: 算术. ...

  4. 一木.溪桥学Python-06:元组tuple、字典dict

    一木.溪桥 在Logic Education跟Amy学Python 12期:Python基础课 一木.溪桥学Python-06:元组tuple.字典dict 日期:2020年12月25日 学习目标: ...

  5. python bar函数循环_一木.溪桥学Python-08: for循环、function函数

    一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-08: fo ...

  6. 一木.溪桥学Python-10:函数闭包、装饰器、推导式

    一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-10:函数闭 ...

  7. 一木.溪桥学Python-11:迭代器、生成器、面象对象class MyClass:、self 参数、 __init__() 方法、__str__() 方法

    一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-11:迭代器 ...

  8. 一木.溪桥学Python-13:多继承、多态、常用魔法方法、单例模式

    一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-13:多继承 ...

  9. 一木.溪桥学Python-04: Python基础数据类型int ,float ,bool ,complex,None,str, 转义字符

    一木.溪桥 在Logic Education跟Amy学Python 12期:Python基础课 一木.溪桥学Python-04: Python基础数据类型int ,float ,bool ,compl ...

最新文章

  1. 一步一步搞定InfoPath(02)--配置VSTA
  2. AndroidStudio项目提交(更新)到github最详细步骤
  3. java 日期注解 xml_Spring xml注解+java注解
  4. Spring MVC入门示例教程--表单处理
  5. Sublime Text3前端必备插件
  6. 飞畅科技教你如何选择合适的交换机?
  7. 前端学习(982):jquery概述
  8. 阿里云安装Quantaxis
  9. 在c语言中定义共用型数据类型的关键字是,C语言的关键字共有32个,根据关键字的作用,可分其为数据类型关键...
  10. 12.Memcached 与 Redis 区别
  11. 解决ubuntu 用anaconda 安装R 语言后,无法安装R语言package的问题
  12. 台式机XP系统调节屏幕亮度
  13. JMeter入门教程
  14. idea修改注释模板
  15. 试图速成的RPG Maker MV 学习笔记(三)
  16. 使用ArcMap 生成TPK和geodatabase包
  17. 3、HeidiSQL数据库管理工具下载与安装
  18. HMI-66-【MeterDisplay for Arm Linux】液晶仪表Arm Linxu迁移
  19. 计算机检测不出移动硬盘,电脑不显示移动硬盘怎么办,检测不到移动硬盘的原因...
  20. Monitor的用法

热门文章

  1. 算法导论 实验三 快速排序及其优化
  2. 高效记忆/形象记忆(08)英语单词记忆-字母熟词拆分
  3. 昌吉学院计算机科学与技术专业,昌吉学院最好的专业是什么、哪些专业比较好...
  4. 解职场困惑不必东奔西走,Leo这里应有尽有(更新至09年8月31日)——Leo文章索引
  5. 最大似然估计到底是怎么一回事
  6. cw2vec: Learning Chinese Word Embeddings with Stroke n-gram Information
  7. android多国语言文件夹文件汇总
  8. linux 下php连接orical数据库
  9. Cloudfront HTTPS 性能优化
  10. 关于公交系统中运用NFC-TSM技术进行移动支付的解决