爬虫入门:urllib库

urllib简单介绍:

urllib属于Python内置库,分四个模块:request,error,parse,robotparser。
Python官方文档:https://docs.python.org/zh-cn/3/library/urllib.html

urllib.request 请求模块

urlopen()函数

urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=None)

import urllib.request
re=urllib.request.urlopen('https://www.python.org')  #请求方式:GET
print(re.read().decode('utf-8')) #输出是Python官网的HTML文档,内容过长,可以自己运行查看结果
#read()方法可以得到网页内容
import urllib.request
re=urllib.request.urlopen('https://www.python.org')
print(type(re)) #结果:<class 'http.client.HTTPResponse'>

由第二段代码可知,urlopen()返回的是HTTPResponse类型的对象。查看文档知,主要包含:read(), readinto(), getheader(name), getheaders(), fileno()等方法,msg, version,status,reason,debuglevel, closed等属性。# 如果觉得插入的图片太模糊,大家可以用print(dir(re))查看所有方法和属性。
在这里插入图片描述
例子:

import urllib.request
re=urllib.request.urlopen('https://www.python.org')
print(re.status)  #得到响应状态码     200表示成功
print(re.getheader('Server'))
print(re.getheaders())
#输出
200
nginx
[('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'DENY'), ('Via', '1.1 vegur'), ('Via', '1.1 varnish'), ('Content-Length', '48272'), ('Accept-Ranges', 'bytes'), ('Date', 'Tue, 16 Jul 2019 06:26:17 GMT'), ('Via', '1.1 varnish'), ('Age', '2510'), ('Connection', 'close'), ('X-Served-By', 'cache-iad2148-IAD, cache-hnd18742-HND'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '1, 3353'), ('X-Timer', 'S1563258378.690692,VS0,VE0'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]

我们还可以传递一些参数:(具体在开头写了)

data参数

如果想要添加data参数,需要用bytes()方法把内容转为字节流编码格式。另:如果传递了这个参数,请求方式将变为POST。bytes第一个参数要求是str()类型,第二个指定编码格式

import urllib.request
import urllib.parse   #需要用urlencode()将字典转为字符串,所以导入这个模块,具体后面会讲
da=bytes(urllib.parse.urlencode({'world':'hello'}),encoding='utf-8')
re=urllib.request.urlopen('http://httpbin.org/post',data=da) 
#这个网站可以用于测试POST请求,网站名就是这个,后面的POST不是定义方法
print(re.read().decode('utf-8'))  #结果太长,自己运行。
timeout参数

这个参数用来设置请求的时间,如果请求时间超出设定值,就会报错。不设置,则用全局默认时间。有了这个参数,可以在一个页面长时间无响应的情况下跳过它,以此提高效率。

import urllib.request
import socket
import urllib.error
try:
	re=urllib.request.urlopen('http://httpbin.org/post',timeout=0.1) #0.1秒一般无法得到响应
except urllib.error.URLError as e:
	if isinstance(e.reason,socket.timeout):
		print('TIME OUT')
# 结果: TIME OUT
其他参数
context

它必须是ssl.SSLContext类型,用于指定SSL设置

cafile 和 capath

分别指定CA证书和它的路径,在请求HTTPS链接时会有用。

cadefault 已经弃用,默认值:False

Request

用urlopen()可以发送最基本的请求,但过于简单,有些功能不够完善,这时就需要Request类来构建

class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverfiable=False, method=None)

  • 第一个参数url为必传参数,用于请求URL。
  • 如果想要添加data参数,需要用bytes()方法把内容转为字节流编码格式。
  • headers是一个字典,它就是请求头,可以在构造请求时通过该参数直接构造,也可以通过add_header()方法添加
  • origin_req_host:指的是请求方的host名称或IP地址
  • unverfiable表示这个请求是否是无法验证,默认为False。
  • method是一个字符串,用于确定请求的方法GET,POST,PUT等
    例子:
from urllib import request,parse
url='https://httpbin.org/post'
headers={
	'User-Agent':'Mozilla/5.0(x11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11'
}
dict={
	'name':'Germey'
}
data=bytes(parse.urlencode(dict),encoding='utf-8')
req=request.Request(url=url,data=data,headers=headers,method='POST')
req.add_header('Host','httpbin.org')
response=request.urlopen(req)
print(response.read().decode('utf-8'))
/*结果
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "Germey"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "11", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Mozilla/5.0(x11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11"
  }, 
  "json": null, 
  "origin": "117.32.216.103, 117.32.216.103", 
  "url": "https://httpbin.org/post"
}*/

Handler

BaseHandler类

它是所有Handler的父类,它提供了最基本的方法,如default_open(), protocol_request()等

  • HTTPDefaultErrorHandler: 用于处理HTTP响应错误
  • HTTPRedirectHandler:用于处理重定向
  • HTTPCookieProcessor:用于处理Cookies
  • ProxyHandler:用于设置代理,默认为空
  • HTTPPasswordMgr:用于管理密码,它维护了用户名和密码的表
  • HTTPBasicAuthHandler:用于解决认证问题

还有其他没列出来的类,可以查看官方文档,在最上面。
例子:

from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError     #后面会讲
username='username'
password='password'
url='https://www.baidu.com'
#创建一个密码管理对象,保存HTTP请求的相关用户名和密码
p=HTTPPasswordMgrWithDefaultRealm()  
#添加账户信息,第一个参数realm是与远程服务器相关的域信息,一般没人管它都是写None,后面三个参数分别是 Web服务器、用户名、密码
p.add_password(None,url,username,password)
#验证Web用户端的用户名和密码
auth_handler=HTTPBasicAuthHandler(p) 
# 通过 build_opener()方法使用这些代理Handler对象,创建自定义opener对象,参数包括构建的 proxy_handler
opener=build_opener(auth_handler)
try:
	result=opener.open(url)
	html=result.read().decode('utf-8')
	print(html)
except URLError as e:
	print(e.reason)
  • Cookie 代理

urllib.error异常处理模块

URLError类

继承自OSError类,是error模块的基类,有一个属性

from urllib import request,error
try:
	re=request.urlopen('http://cuiqingcai.com/index.htm')
except error.URLError as e:
	print(e.reason)   #返回原因
#结果
Not Found

HTTPError

URLError的子类,专门用来处理HTTP请求错误,有三个属性

from urllib import request,error
try:
	re=request.urlopen('http://cuiqingcai.com/index.htm')
except error.HTTPError as e:
	print(e.reason,e.code,e.headers,sep='\n')   #返回原因,HTTP状态码,返回请求头
#结果
Not Found
404
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 16 Jul 2019 09:16:10 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
Set-Cookie: PHPSESSID=s3vh0l6oq998aamggquls21gh3; path=/
Pragma: no-cache
Vary: Cookie
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Link: <https://cuiqingcai.com/wp-json/>; rel="https://api.w.org/"

parse处理URL模块

urlparse()

urlparse(urlstring, scheme=’’, allow_fragments=True)

URL的识别和分段;标准连接的格式:scheme://netloc/path;params?query#fragment

from urllib.parse import urlparse

#如果不带协议信息,则scheme将会成为默认协议
result=urlparse('www.baidu.com/index.html;user?id=5#comment',scheme='https')
print(result)
#结果:ParseResult(scheme='https', netloc='', path='www.baidu.com/index.html', params='user', query='id=5', fragment='comment')

#如果同时带上scheme和参数,且二者不同
result=urlparse('http://www.baidu.com/index.html;user?id=5#comment',scheme='https')
print(result)
结果:ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')

#如果设置allow_fragments=False,fragment会为空,它的值会成为path,parameters或者query的一部分
result=urlparse('http://www.baidu.com/index.html;user?id=5#comment',allow_fragments=False)
print(result)
#结果:ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5#comment', fragment='')

#ParseResult的结果实则是元祖,我们可用索引顺序或属性名获取
result=urlparse('http://www.baidu.com/index.html#comment',allow_fragments=False)
print(result.scheme,result[0],result.netloc,result[1],sep='\n')
#结果:
http
http
www.baidu.com
www.baidu.com

urlunparse

和urlparse相对,接受的参数是一个可迭代对象,长度必须是6,否则报错

from urllib.parse import urlunparse
data=['http','www.baidu.com','index.htnl','user','a=6','comment']
#data也可为元祖或其他特定数据结构
print(urlunparse(data))
# http://www.baidu.com/index.htnl;user?a=6#comment

urlsplit()

与urlparse()方法类似,但它不再单独解析params这一部分,只返回5个结果,params和path合并
返回的SplitResult同样为元祖类型,同样可用索引,属性获取值

urlunsplit()

与urlunparse()类似,但传入参数长度必须是5

urljoin()

我们提供一个base_url作为第一个参数,把新链接做第二个参数,该方法会把base_url的scheme, netloc, path这三个在新链接缺失的部分进行补充,params, query, fragment 不起作用。

urlencode()

例子:

from urllib.parse import urlencode
params={
	'name':'germy',
	'age':'22'
}
base_url='http://www.baidu.com?'
url=base_url+urlencode(params)  #把字典转为URL参数
print(url)   #http://www.baidu.com?name=germy&age=22

parse_qs()

把GET请求参数转为字典

parse_ql()

把参数转为元祖组成的列表,每个元祖第一个值为参数名,第二个为值。

quote()

把内容转为URL编码格式

unquote()

把URL进行解码

Robots协议

set_url()

设置robots.txt文件链接,在创建RobotFileParser对象时如果有链接就不需要

read()

读取robots.txt文件,必须有,它不会返回任何值。

parse()

解析robots.txt文件,传入的参数是robots.txt某些行内容。

can_fetch()

传入两个参数User-agent, URL返回搜索引擎是否可以抓取这个URL,True和False

mtime()

返回上次抓取和分析robots.txt文件的时间

modified()

将当前时间设置为上次抓取和分析robots.txt文件的时间

例子:

>>> import urllib.robotparser
>>> rp = urllib.robotparser.RobotFileParser()
>>> rp.set_url("http://www.musi-cal.com/robots.txt")
>>> rp.read()
>>> rrate = rp.request_rate("*")
>>> rrate.requests
3
>>> rrate.seconds
20
>>> rp.crawl_delay("*")
6
>>> rp.can_fetch("*", "http://www.musi-cal.com/cgi-bin/search?city=San+Francisco")
False
>>> rp.can_fetch("*", "http://www.musi-cal.com/")
True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值