urllib模块

0.urllib是什么

是Python的内置模块

1.为啥要学urllib

1.用于对比第三方库的学习
2.有的项目是用urllib写的
3.request请求+urllib保存文件方便

  1. import requests
  2. url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1113%2F092919113248%2F1Z929113248-8-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1648693445&t=ea8a4fa8599404cb90a7273342cd169f'
  3. re = requests.get(url)
  4. with open('picture.png','wb') as f: #一般爬音频图片用wb
  5. f.write(re.content) #一般爬音频图片用content
  1. import requests
  2. from urllib import request
  3. url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1113%2F092919113248%2F1Z929113248-8-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1648693445&t=ea8a4fa8599404cb90a7273342cd169f'
  4. re = requests.get(url)
  5. request.urlretrieve(url,'picture2.png')#第二个参数可以是文件名(会在本文件夹建一个文件)
  6. 也可以是文件路径

2.urllib的常用模块之request模块

  1. urllib.request.urlopen(网站链接)
  2. urllib.request.urlopen(请求对象)
  3. 作用:发送请求,并返回一个对象

使用urllib爬取百度

  1. import urllib.request
  2. url = 'https://www.baidu.com/'
  3. respones = urllib.request.urlopen(url)
  4. print(respones.read())
  5. >>>b'<html>\r\n<head>\r\n\t<script>\r\n\t\
  6. tlocation.replace(location.href.replace("https://","http://"));\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript>
  7. <meta http-equiv="refresh"
  8. content="0;url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>'

这样爬取发现问题:
1.数据是字节不是方便操作的数据类型 ——> 解码

  1. import urllib.request
  2. url = 'https://www.baidu.com/'
  3. respones = urllib.request.urlopen(url)
  4. print(respones.read().decode('utf-8'))
  5. >>>
  6. <html>
  7. <head>
  8. <script>
  9. location.replace(location.href.replace("https://","http://"));
  10. </script>
  11. </head>
  12. <body>
  13. <noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>
  14. </body>
  15. </html>

2.通过查看源码的方式发现爬取的数据与网页里的数量不一致 ——> 认出是爬虫不给数据,重构做个头

  1. import urllib.request
  2. url = 'https://www.baidu.com/'
  3. headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Mobile Safari/537.36"}
  4. respones = urllib.request.urlopen(url,headers = headers)
  5. print(respones.read().decode('utf-8'))
  6. >>>TypeError: urlopen() got an unexpected keyword argument 'headers'

想要重构头需要另一个方法:urllib.request.Request(url,headers = headers)形成一个有头的请求对象UA

  1. import urllib.request
  2. url = 'https://www.baidu.com/'
  3. headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Mobile Safari/537.36"}
  4. request_obj = urllib.request.Request(url,headers = headers)
  5. response_result = urllib.request.urlopen(request_obj)
  6. print(response_result.read().decode('utf-8')

补充:

  1. print(response_result.getcode())
  2. 放在urllib.request.urlope()返回的对象后可以看到请求的状态码,养成习惯
  3. >>>200
  4. print(response_result.geturl())
  5. print(response_result.status)
  6. 查看请求对象的请求地址
  7. >>>https://www.baidu.com/
  8. print(response_result.getheaders())
  9. 获得全部请求头
  10. print(response_result.getheaders('Bdpagetype'))
  11. >>> 1
  12. 可以传参,想要啥值就传入啥参数就可以打印出对应的值

3.urllib的常用模块之parse模块

应用:当我们用url搜索时,浏览器会将url中除了字母数字部分符号外的其他转化成16进制,所以我们写爬虫的时候如果由汉字或其他浏览器读不懂的东西要把它解析

  1. import urllib.request
  2. url1 = 'https://www.baidu.com/s?wd=%E5%A5%A5%E8%BF%90%E4%BC%9A'
  3. url2 = 'https://www.baidu.com/s?wd=奥运会'
  4. response_result = urllib.request.urlopen(url1)
  5. response_result = urllib.request.urlopen(url2) #UnicodeEncodeError
  6. 需要把url2转化成url1的样子,三个%表示一个汉字

方法一:urlencode()编码

  1. import urllib.request
  2. import urllib.parse
  3. url2 = 'https://www.baidu.com/s?wd=奥运会'
  4. r = {"wd":'奥运会'} #把要转化的参数与值写入字典
  5. re = urllib.parse.urlencode(r) #传入字典,并接收返回的值
  6. url3 = 'https://www.baidu.com/s?' + re #字符串进行拼接,直接把url编码会出错,只能拼接
  7. print(url3)
  8. response_result = urllib.request.urlopen(url3)

方法二:quote()编码

  1. import urllib.request
  2. import urllib.parse
  3. url2 = 'https://www.baidu.com/s?wd=奥运会'
  4. r = '奥运会' #准备好要转化的字符串
  5. re = urllib.parse.quote(r) #传入字符串,并接收返回的值
  6. url3 = 'https://www.baidu.com/s?wd=' + re
  7. print(url3) ##字符串进行拼接,直接把url编码会出错,只能拼接
  8. response_result = urllib.request.urlopen(url3)

4.解码

url里有一堆%,需要解码

  1. import urllib.request
  2. import urllib.parse
  3. url = 'https%3A%2F%2Fshp%2Eqpic%2Ecn%2Fishow%2F2735022317%2F1645610274%5F1265602313%5F44569%5FsProdImgNo%5F1%2Ejpg%2F200'
  4. print(urllib.request.unquote(url))
  5. >>>https://shp.qpic.cn/ishow/2735022317/1645610274_1265602313_44569_sProdImgNo_1.jpg/200

5.案例

批量处理:把一些网址的参数转成字典形式,再通过urlencode()方法转化成字符串,进而拼出自己需要的url
为啥需要拼url:这样可以实现对一个网址的动态爬取输入自己想要爬取的主题,页数。
在哪里获得url里的参数:
image.png

  1. #1.ctrl+R 出现一个框
  2. #2.选择.*进入正则模式
  3. #3.在框内输入(.*?):(.*)
  4. # "$1":"$2",
  5. #4.点击匹配全部 replace all
  6. #5.字典转成字符串urlencode(字典)方法
  7. #6.拼出自己需要的url
  8. #将参数复制进来
  9. kw: 蜡笔小新
  10. ie: utf-8
  11. pn: 0
  12. #做前四项操作
  13. "kw":" 蜡笔小新",
  14. "ie":" utf-8",
  15. "pn":" 0",
  16. #把它们放入字典转化成字符串
  17. import urllib.parse
  18. dict = {"kw": "蜡笔小新","ie": "utf-8","pn": "0"}
  19. dict_str = urllib.parse.urlencode(dict)
  20. print(dict_str)
  21. >>>kw=%E8%9C%A1%E7%AC%94%E5%B0%8F%E6%96%B0&ie=utf-8&pn=0
  22. url之后再拼接就可以了