爬虫之urllib包以及request模块和parse模块
urllib简介
简介
Python3中将python2.7的urllib和urllib2两个包合并成了一个urllib库
Python3中,urllib库包含有四个模块:
- urllib.request 主要用来打开或者读取url
- urllib.error 主要用来存放返回的错误信息
- urllib.parse 主要用来解析url
- urllib.robotparser 主要用来解析robots.txt文件
模块安装与导入
urllib是python自带的一个包,无需安装,导入方法如下:
1
2
|
from
urllib
import
request
...
|
urllib.request
urllib.request这个模块用得比较多, 尤其是urlopen函数,会返回一个二进制的对象,对这个对象进行read()操作可以得到一个包含网页的二进制字符串,然后用decode()解码成一段html代码:
语法结构:
1
|
urllib.request.urlopen(url,data
=
None
,[timeout,]
*
,cafile
=
None
, capath
=
None
, cadefault
=
False
, context
=
None
)
|
参数:其中url既可以是一个URL字符串,又可以是一个Requst对象,一般使用后者添加其他参数。
当request的方式是post时,使用参数data,用于填写传递的表单信息,将data填好表单信息,准备传入urlopen 前,还需要利用urllib.parse里的urlencode()函数转换格式,写成data = urllib.parse.urlencode(data).encode(‘’),然后将data传入函数。
而urllib.request的Request函数,也可以用于打开url字符串,同时可以传入更多的参数,例如:headers,Request函数可以返回一个request对象作为urlopen函数的url参数使用。
语法结构:
1
|
urllib.request. Request(url, data
=
None
, headers
=
{}, origin_req_host
=
None
, unverifiable
=
False
, method
=
None
)
|
参数:其中url是一个URL字符串。
data用法与urlopen一致。
headers参数是一个字典,服务器对于用户发出的request,会通过其中的headers信息来判断用户发信息,我们可以通过自己编写headers传入urllib.request. Request中用于伪装自己的身份。Header中User-agent参数是判断用户身份。另外通过设置代理可以改变用户提交时的IP地址。
爬虫之urllib.error模块
error模块简介
我们在爬虫的时候发请求的时候难免出现错误,如访问不到服务器或者访问被禁止等等,
出错了之后urllib将错误信息封装成了一个模块对象中,这个模块就叫error模块
error的分类
分为URLError和HTTPError。
URLError是OSError的一个子类
有以下错误的时候错误信息就会被封装在URLError里:
- 无网络
- 有网络但是由于种种原因导致服务器连接失败
而如果能够连接服务器但是服务器返回了错误代码如404,403等等(400以上),那么催无信息就会被封装在HTTPError里
URLError与HttpError的区别和关系
区别:
- URLError封装的错误信息一般是由网络引起的,包括url错误
- HTTPError封装的错误信息一般是服务器返回了错误状态码
关系:
- URLError是OSERROR的子类,HTTPError是URLError的子类
使用方法
error类是在捕获错误信息的时候使用,而且一般我们也需要进行捕获,因为你很难确定访问请求一定不会出现错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
from
urllib
import
request
from
urllib
import
error
url
=
'http://baiduuuu.com'
try
:
res
=
request.Request(url)
response
=
request.urlopen(res)
print
(response.read().decode())
except
error.HTTPError as he:
print
(he)
# print(he.reason)
except
error.URLError as ue:
print
(ue)
# print(ue.reason)
except
Exception as e:
print
(e)
|
注意:由于HTTPError是URLError的子类,所以捕获的时候HTTPError要放在URLError的上面
urllib.parse
待续......
urllib.robotparser
待续......
爬虫小示例
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
from
urllib
import
request
# 定义一个url
url
=
'https://www.baidu.com/'
# 用request.urlopen()方法打开指定的url
response
=
request.urlopen(url)
# 返回的是一个HTTPResponse对象
print
(
type
(response))
# <class 'http.client.HTTPResponse'>
print
(response)
# <http.client.HTTPResponse object at 0x00000196C95CB550>
# 调用返回的response对象的read()方法,可以读取url返回的html内容,不过是bytes类型的
html
=
response.read()
print
(
type
(html))
# <class 'bytes'>
# 对bytes类型的html进行解码
html
=
html.decode()
print
(html)
|
分析
根据以上代码,我们得知,urllib包下面的request模块的urlopen方法可以获取一个HttpResponse对象,通过调用对象的read()方法可以获取二进制格式的url的html内容,对结果进行解码即可
urlopen返回的HttpResonse对象
我们从上面的小示例可以看出,urlopen打开一个url后会返回一个HttpResponse对象,这个对象有以下几个常用的方法:
read()
次方法用来读取url的html内容,格式为二进制
geturl()
用来获取urlopen的url参数,也就是所打开的url
如,在上面示例中调用此方法:
1
2
3
|
print
(response.geturl())
# https://www.baidu.com/
|
info()
返回response对象的meta信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
print
(response.info())
'''
Accept-Ranges: bytes
Cache-Control: no-cache
Content-Length: 227
Content-Type: text/html
Date: Wed, 09 May 2018 13:59:22 GMT
Last-Modified: Tue, 08 May 2018 03:45:00 GMT
P3p: CP=" OTI DSP COR IVA OUR IND COM "
Pragma: no-cache
Server: BWS/1.1
Set-Cookie: BD_NOT_HTTPS=1; path=/; Max-Age=300
Set-Cookie: BIDUPSID=E163F6688178D6656D765FF58DBA2D01; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1525874362; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=0
X-Ua-Compatible: IE=Edge,chrome=1
Connection: close
'''
|
getcode()
返回http状态码。200 404 403等
1
2
3
|
print
(response.getcode())
# 200
|
给urlopen传递参数
get方法传参
利用url参数给服务器传递信息
参数为dict类型,需要用parse对字典参数进行编码
格式为:
1
|
response
=
request.urlopen(url,data)
|
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
from
urllib
import
request
from
urllib
import
parse
url
=
'https://www.baidu.com/s'
# 让用户输入关键词
keyword
=
input
(
'请输入您要搜索的内容:'
)
# 定义一个字典,将用户输入的关键字封装到里面
data
=
{
'kw'
:keyword}
# 对data进行编译
data
=
parse.urlencode(data).encode()
response
=
request.urlopen(url,data)
print
(response.read().decode())
|
上面的小示例是直接用给urlopen的data传参数的形式来传递数据,也可以将参数数据封装给一个Request对象,然后将对象再传递给urlopen。
这种方法可以传递更多的信息,如header等,可以更好的隐藏我们身份,伪装成浏览器访问,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from
urllib
import
request
from
urllib
import
parse
keyword
=
input
(
'请输入您要搜索的内容:'
)
url
=
'https://www.baidu.com/s'
data
=
{
'kw'
:keyword}
header
=
{
'Content-Length'
:
len
(data)}
req
=
request.Request(url,data
=
parse.urlencode(data).encode(),headers
=
header)
response
=
request.urlopen(req)
print
(response.read().decode())
|
post方法传参
连接百度翻译接口的小示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
from
urllib
import
request
from
urllib
import
parse
url
=
'http://fanyi.baidu.com/sug'
keyword
=
input
(
'请输入您要翻译的词语'
)
data
=
{
'kw'
:keyword}
data
=
parse.urlencode(data).encode()
header
=
{
'Content-Length'
:
len
(data)}
res
=
request.Request(url,data
=
data,headers
=
header)
response
=
request.urlopen(res)
res
=
response.read().decode()
print
(res)
|
上面的小示例返回的是一个json类型的字典,输入'girl'之后翻译结果如下:
1
|
{
"errno"
:
0
,
"data"
:[{
"k"
:
"girl"
,
"v"
:
"n. \u5973\u5b69; \u59d1\u5a18\uff0c\u672a\u5a5a\u5973\u5b50; \u5973\u804c\u5458\uff0c\u5973\u6f14\u5458; \uff08\u7537\u4eba\u7684\uff09\u5973\u670b\u53cb;"
},{
"k"
:
"girls"
,
"v"
:
"n. \u5973\u5b69; \u5973\u513f( girl\u7684\u540d\u8bcd\u590d\u6570 ); \u5973\u5de5; \uff08\u7537\u4eba\u7684\uff09\u5973\u670b\u53cb;"
},{
"k"
:
"girlfriend"
,
"v"
:
"n. \u5973\u670b\u53cb; \u5973\u6027\u670b\u53cb;"
},{
"k"
:
"girl friend"
,
"v"
:
"n. \u5973\u670b\u53cb\uff0c\uff08\u7537\u4eba\u7684\uff09\u60c5\u4eba; \u5bf9\u8c61;"
},{
"k"
:
"Girls' Generation"
,
"v"
:
" \u5c11\u5973\u65f6\u4ee3\uff08\u97e9\u56fdSM\u5a31\u4e50\u6709\u9650\u516c\u53f8\u4e8e2007\u5e74\u63a8\u51fa\u7684\u4e5d\u540d\u5973\u5b50\u5c11\u5973\u7ec4\u5408\uff09;"
}]}
|
我们只需要用json给它转成字典格式,然后循环展示即可查看到结果,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
from
urllib
import
request
from
urllib
import
parse
import
json
url
=
'http://fanyi.baidu.com/sug'
keyword
=
input
(
'请输入您要翻译的词语'
)
data
=
{
'kw'
:keyword}
data
=
parse.urlencode(data).encode()
header
=
{
'Content-Length'
:
len
(data)}
res
=
request.Request(url,data
=
data,headers
=
header)
response
=
request.urlopen(res)
res
=
response.read().decode()
fanyi_res
=
json.loads(res)[
'data'
]
for
item
in
fanyi_res:
print
(item[
'k'
],item[
'v'
])
|
结果如下:
1
2
3
4
5
6
|
请输入您要翻译的词语girl
girl n. 女孩; 姑娘,未婚女子; 女职员,女演员; (男人的)女朋友;
girls n. 女孩; 女儿( girl的名词复数 ); 女工; (男人的)女朋友;
girlfriend n. 女朋友; 女性朋友;
girl friend n. 女朋友,(男人的)情人; 对象;
Girls' Generation 少女时代(韩国SM娱乐有限公司于
2007
年推出的九名女子少女组合);
|