Python爬虫中urllib库的进阶学习


Posted in Python onJanuary 05, 2018

urllib的基本用法

urllib库的基本组成

利用最简单的urlopen方法爬取网页html

利用Request方法构建headers模拟浏览器操作

error的异常操作

urllib库除了以上基础的用法外,还有很多高级的功能,可以更加灵活的适用在爬虫应用中,比如:

使用HTTP的POST请求方法向服务器提交数据实现用户登录

使用代理IP解决防止反爬

设置超时提高爬虫效率

解析URL的方法

本次将会对这些内容进行详细的分析和讲解。

POST请求

POST是HTTP协议的请求方法之一,也是比较常用到的一种方法,用于向服务器提交数据。博主先介绍进行post请求的一些准备工作,然后举一个例子,对其使用以及更深层概念进行详细的的剖析。

POST请求的准备工作

既然要提交信息给服务器,我们就需要知道信息往哪填,填什么,填写格式是什么?带这些问题,我们往下看。

同样提交用户登录信息(用户名和密码),不同网站可能需要的东西不一样,比如淘宝反爬机制较复杂,会有其它一大串的额外信息。这里,我们以豆瓣为例(相对简单),目标是弄清楚POST是如何使用的,复杂内容会在后续实战部分与大家继续分享。

抛出上面像淘宝一样需要的复杂信息,如果仅考虑用户名和密码的话,我们的准备工作其实就是要弄明白用户名和密码标签的属性name是什么,以下两种方法可以实现。

浏览器F12查看element获取

也可以通过抓包工具Fiddler获取。

废话不多说了,让我们看看到底如何找到name?

1. 浏览器F12

通过浏览器F12元素逐层查看到(我是用的Chrome),邮箱/手机号标签的name="form_email", 密码的标签name="form_email",如下图红框所示。

Python爬虫中urllib库的进阶学习

但要说明的是,两个标签的name名称并不是固定的,上面查看的name名称只是豆瓣网站定义的,不代表所有。其它的网站可能有会有不同的名称,比如name="username", name="password"之类的。因此,针对不同网站的登录,需要每次查看name是什么。

2. 通过fiddler抓包工具

Python爬虫中urllib库的进阶学习

博主推荐使用fiddler工具,非常好用。爬虫本身就是模拟浏览器工作,我们只需要知道浏览器是怎么工作的就可以了。

fiddler会帮助我们抓取浏览器POST请求的所有内容,这样我们得到了浏览器POST的信息,把它填到爬虫程序里模拟浏览器操作就OK了。另外,也可以通过fiddler抓到浏览器请求的headers,非常方便。

安装fiddler的小伙伴们注意:fiddler证书问题的坑(无法抓取HTTPs包),可以通过Tools —> Options —>HTTPS里面打勾Decrypt HTTPS traffic修改证书来解决。否则会一直显示抓取 Tunnel 信息包...

好了,完成了准备工作,我们直接上一段代码理解下。

POST请求的使用

# coding: utf-8
import urllib.request
import urllib.error
import urllib.parse

# headers 信息,从fiddler上或你的浏览器上可复制下来
headers = {'Accept': 'text/html,application/xhtml+xml,
    application/xml;q=0.9,image/webp,image/apng,
    */*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; 
           Win64; x64) AppleWebKit/537.36 
           (KHTML, like Gecko)Chrome/48.0
           .2564.48 Safari/537.36'
    }
# POST请求的信息,填写你的用户名和密码
value = {'source': 'index_nav',
   'form_password': 'your password',
   'form_email': 'your username'
   }
try:
data = urllib.parse.urlencode(value).encode('utf8')
response = urllib.request.Request(
'https://www.douban.com/', data=data, headers=headers)
html = urllib.request.urlopen(response)
result = html.read().decode('utf8')
print(result)
except urllib.error.URLError as e:
if hasattr(e, 'reason'):
  print('错误原因是' + str(e.reason))
except urllib.error.HTTPError as e:
if hasattr(e, 'code'):
  print('错误编码是' + str(e.code))
else:
print('请求成功通过。')

运行结果:

<!DOCTYPE HTML>
<html lang="zh-cmn-Hans" class="ua-windows ua-webkit">
<head>
<meta charset="UTF-8">
<meta name="description" content="提供图书、电影、音乐唱片的
推荐、评论和价格比较,以及城市独特的文化生活。">
.....
window.attachEvent('onload', _ga_init);
}
</script>
</body>
</html>

注意:复制header的时候请去掉 这一项'Accept-Encoding':' gzip, deflate, 否则会提示decode的错误。

POST请求代码分析

我们来分析一下上面的代码,与urllib库request的使用基本一致,urllib库request的基本用法可参考上篇文章Python从零学爬虫,这里多出了post的data参数和一些解析的内容,着重讲解一下。

data = urllib.parse.urlencode(value).encode('utf8')

这句的意思是利用了urllib库的parse来对post内容解析,为什么要解析呢?

这是因为post内容需要进行一定的编码格式处理后才能发送,而编码的规则需要遵从RFC标准,百度了一下RFC定义,供大家参考:

Request ForComments(RFC),是一系列以编号排定的文件。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件。目前RFC文件是由InternetSociety(ISOC)赞助发行。基本的互联网通信协议都有在RFC文件内详细说明。RFC文件还额外加入许多的论题在标准内,例如对于互联网新开发的协议及发展中所有的记录。因此几乎所有的互联网标准都有收录在RFC文件之中。

而parse的urlencode方法是将一个字典或者有顺序的二元素元组转换成为URL的查询字符串(说白了就是按照RFC标准转换了一下格式)。然后再将转换好的字符串按UTF-8的编码转换成为二进制格式才能使用。

注:以上是在Python3.x环境下完成,Python3.x中编码解码规则为 byte—>string—>byte的模式,其中byte—>string为解码,string—>byte为编码

代理IP

代理IP的使用

为什么要使用代理IP?因为各种反爬机制会检测同一IP爬取网页的频率速度,如果速度过快,就会被认定为机器人封掉你的IP。但是速度过慢又会影响爬取的速度,因此,我们将使用代理IP取代我们自己的IP,这样不断更换新的IP地址就可以达到快速爬取网页而降低被检测为机器人的目的了。

同样利用urllib的request就可以完成代理IP的使用,但是与之前用到的urlopen不同,我们需要自己创建订制化的opener。什么意思呢?

urlopen就好像是opener的通用版本,当我们需要特殊功能(例如代理IP)的时候,urlopen满足不了我们的需求,我们就不得不自己定义并创建特殊的opener了。

request里面正好有处理各种功能的处理器方法,如下:

ProxyHandler, UnknownHandler, HTTPHandler,
HTTPDefaultErrorHandler, HTTPRedirectHandler,
FTPHandler, FileHandler, HTTPErrorProcessor, DataHandler

我们要用的是第一个ProxyHandler来处理代理问题。

让我们看一段代码如何使用。

# coding:utf-8
import urllib.request
import urllib.error
import urllib.parse
# headers信息,从fiddler上或浏览器上可复制下来
headers = {'Accept': 'text/html,application/xhtml+xml,
    application/xml;q=0.9,image/webp,image/apng,
    */*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3;
           Win64;
           x64) AppleWebKit/537.36 (KHTML, 
           like Gecko)Chrome/48.0.2564.48 
           Safari/537.36'
    }
# POST请求的信息
value = {'source': 'index_nav',
   'form_password': 'your password',
   'form_email': 'your username'
   }
# 代理IP信息为字典格式,key为'http',value为'代理ip:端口号'
proxy = {'http': '115.193.101.21:61234'}
try:
data = urllib.parse.urlencode(value).encode('utf8')
response = urllib.request.Request(
'https://www.douban.com/', data=data, headers=headers)
# 使用ProxyHandler方法生成处理器对象
proxy_handler = urllib.request.ProxyHandler(proxy)
# 创建代理IP的opener实例
opener = urllib.request.build_opener(proxy_handler)
# 将设置好的post信息和headers的response作为参数
html = opener.open(response)
result = html.read().decode('utf8')
print(result)
except urllib.error.URLError as e:
if hasattr(e, 'reason'):
  print('错误原因是' + str(e.reason))
except urllib.error.HTTPError as e:
if hasattr(e, 'code'):
  print('错误编码是' + str(e.code))
else:
print('请求成功通过。')

在上面post请求代码的基础上,用自己创建的opener替换urlopen即可完成代理IP的操作,代理ip可以到一些免费的代理IP网站上查找。

以上就是我们整理的全部内容,感谢你对三水点靠木的支持。

Python 相关文章推荐
python 字符串格式化代码
Mar 17 Python
Python进行数据科学工作的简单入门教程
Apr 01 Python
Python在线运行代码助手
Jul 15 Python
Python简单获取自身外网IP的方法
Sep 18 Python
python实现周期方波信号频谱图
Jul 21 Python
在python中bool函数的取值方法
Nov 01 Python
python文件拆分与重组实例
Dec 10 Python
阿里云ECS服务器部署django的方法
Aug 29 Python
pd.DataFrame统计各列数值多少的实例
Dec 05 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
Jun 24 Python
Python numpy大矩阵运算内存不足如何解决
Nov 19 Python
为了顺利买到演唱会的票用Python制作了自动抢票的脚本
Oct 16 Python
浅谈django model postgres的json字段编码问题
Jan 05 #Python
django admin添加数据自动记录user到表中的实现方法
Jan 05 #Python
Python3 queue队列模块详细介绍
Jan 05 #Python
python多进程中的内存复制(实例讲解)
Jan 05 #Python
使用python和Django完成博客数据库的迁移方法
Jan 05 #Python
Python3多线程爬虫实例讲解代码
Jan 05 #Python
python编写微信远程控制电脑的程序
Jan 05 #Python
You might like
javascript操作文本框readOnly
2007/05/15 Javascript
jscript之List Excel Color Values
2007/06/13 Javascript
Firefox div高度自适应
2009/04/28 Javascript
一个基于jquery的图片切换效果
2010/07/06 Javascript
基于jquery的仿百度的鼠标移入图片抖动效果
2010/09/17 Javascript
js中格式化日期时间型数据函数代码
2010/11/08 Javascript
jquery的选择器的使用技巧之如何选择input框
2013/09/22 Javascript
深入理解javascript变量声明
2014/11/20 Javascript
BootStrap智能表单demo示例详解
2016/06/13 Javascript
javascript 判断页面访问方式电脑或者移动端
2016/09/19 Javascript
让DIV的滚动条自动滚动到最底部的3种方法(推荐)
2016/09/24 Javascript
使用微信内嵌H5网页解决JS倒计时失效问题
2017/01/13 Javascript
在Js页面通过POST传递参数跳转到新页面详解
2017/08/25 Javascript
vue-router 组件复用问题详解
2018/01/22 Javascript
详解Nuxt.js部署及踩过的坑
2018/08/07 Javascript
原生javascript实现类似vue的数据绑定功能示例【观察者模式】
2020/02/24 Javascript
[01:14]3.19DOTA2发布会 三代刀塔人第二代
2014/03/25 DOTA
Python常用列表数据结构小结
2014/08/06 Python
python开发中module模块用法实例分析
2015/11/12 Python
Python基于列表list实现的CRUD操作功能示例
2018/01/05 Python
浅谈Python基础—判断和循环
2019/03/22 Python
如何实现更换Jupyter Notebook内核Python版本
2020/05/18 Python
用python按照图像灰度值统计并筛选图片的操作(PIL,shutil,os)
2020/06/04 Python
Python生成并下载文件后端代码实例
2020/08/31 Python
详解CSS3 filter:drop-shadow滤镜与box-shadow区别与应用
2020/08/24 HTML / CSS
伦敦一家西班牙童装精品店:La Coqueta
2018/02/02 全球购物
Topshop法国官网:英国快速时尚品牌
2018/04/08 全球购物
英语专业个人求职自荐信
2013/09/21 职场文书
材料物理专业大学毕业生求职信
2013/10/15 职场文书
事业单位考核材料
2014/05/21 职场文书
亮剑精神演讲稿
2014/05/23 职场文书
中学生自我评价2015
2015/03/03 职场文书
物流仓管员岗位职责
2015/04/01 职场文书
2019如何书写演讲稿?
2019/07/01 职场文书
springboot + mongodb 通过经纬度坐标匹配平面区域的方法
2021/11/01 MongoDB
基于Python实现将列表数据生成折线图
2022/03/23 Python