目录
- urllib库
urllib库
python内置的http请求库
官方文档:https://docs.python.org/3/library/urllib.html
一个web测试网站:http://httpbin.org
1.urllib.request(请求模块)
urlopen
发送请求
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
- url:链接,字符串
- data:post方式表单,bytes类型
- data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding='utf8')
- bytes方法第一个参数字符串类型,第二个第二个参数指定编码格式,urlencode将参数字典转化为字符串
- timeout:设置超时,单位秒,超过未响应会报URLError异常
- context:必须是ssl.SSLContext类型,用来指定SSL设置
- cafile和capath:分别指定CA证书和它的路径,请求HTTPS链接时会有用
Request
封装请求,得到请求对象,传给urlopen,请求对象属性和方法文档:https://docs.python.org/3/library/urllib.request.html#request-objects
request = urllib.request.Request('https://python.org')
response = urllib.request.urlopen(request)
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
- headers:是一个字典,请求头
- 通过修改User-Agent来伪装浏览器,默认的User-Agent是Python-urllib
- headers也可以用add_header('请求头名称','值')方法来直接添加到封装后的请求
- origin_req_host:请求方的host名称或者IP地址
- unverifiable:请求是否是没有足够权限接收请求的结果,默认是False,意思有权限
- method:字符串,用来指示请求使用的方法
urlretrieve(python2的遗留接口)
直接将远程数据下载到本地,方法返回一个包含两个元素的(filename, headers) 元组,filename 表示保存该到本地的路径,header表示服务器的响应头
urllib.request.urlretrieve(url[,filename[,reporthook[,data]]])
- filename指定了保存本地路径(如果参数未指定,urllib会生成一个临时文件保存数据。)
-
reporthook是一个回调函数,当连接上服务器、以及相应的数据块传输完毕时会触发该回调,我们可以利用这个回调函数来显示当前的下载进度。
def callback(dbnum, dbsize, size): '''回调函数 dbnum: 已经下载的数据块 dbsize: 数据块的大小 size: 远程文件的大小 ''' percent = 100.0 * dbnum * dbsize / size if percent > 100: percent = 100 print "%.2f%%"% percent
-
data指post到服务器的数据
Handler工具和OpenerDirector类
利用Handler来构建Opener,Opener可以使用open()方法,返回response.提供了高级的操作(比如Cookies处理、代理设置等)
-
BaseHandler类,它是所有其他Handler的父类,它提供了最基本的方法,例如default_open()、protocol_request()
- 其他Handler
- HTTPDefaultErrorHandler:用于处理HTTP响应错误,错误都会抛出HTTPError类型的异常。
- HTTPRedirectHandler:用于处理重定向。
- HTTPCookieProcessor:用于处理Cookies。
- ProxyHandler:用于设置代理,默认代理为空。
- HTTPPasswordMgr:用于管理密码,它维护了用户名和密码的表。
- HTTPBasicAuthHandler:用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题
+ 更多
-
验证页面(用户名和密码)
from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLError
username = 'username'
password = 'password'
url = 'http://localhost:5000/'
p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
auth_handler = HTTPBasicAuthHandler(p)
opener = build_opener(auth_handler) # 用handle构建opener
try:
result = opener.open(url)
html = result.read().decode('utf-8')
print(html)
except URLError as e:
print(e.reason)
- 代理
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
# socks代理,全局代理,requests库相同,设置后正常请求就可
# import socket # pip3 install PySocks
# import scoks
# socks . set_default_proxy(socks.SOCKSS ,’ 127.0.0 . 1 ’, 9742)
# socket . socket = socks.socksocket
# http代理
proxy_handler = ProxyHandler({
'http': 'http://127.0.0.1:9743',
'https': 'https://127.0.0.1:9743'
# 需要认证就http://uesrname:password@127.0.0.1:9743
})
opener = build_opener(proxy_handler)
try:
response = opener.open('https://www.baidu.com')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
- cookie
import http.cookiejar, urllib.request
cookie = http.cookiejar.CookieJar() # 直接获取
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
for item in cookie:
print(item.name+"="+item.value)
filename = 'cookies.txt' # 写入文件
cookie = http.cookiejar.MozillaCookieJar(filename)
# MozillaCookieJar是CookieJar的子类,可以用来处理Cookies和文件相关的事件,比如读取和保存Cookies,可以将Cookies保存成Mozilla型浏览器的Cookies格式.LWPCookieJar会保存成libwww-perl(LWP)格式的Cookies文件。
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)
cookie = http.cookiejar.LWPCookieJar() # 从文件中读取并利用cookie
cookie.load('cookies.txt', ignore_discard=True, ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
print(response.read().decode('utf-8'))
2.response对象
是http.client.HTTPResponse类的实例
方法
- read([amt]):读取并返回响应正文,或者返回下一个amt字节
- readinto(b):将响应主体的下一个len(b)字节读入缓冲区b。返回读取的字节数
- getheader(name, default=None):通过响应头的键返回相应的值,可以多个
- getheaders():返回响应头
- fileno():返回fileno底层套接字
- geturl():返回检索到的资源的URL,通常用于确定是否遵循重定向
- info():以email.message_from_string()实例的形式返回页面的元信息,例如标题
- getcode():返回响应的HTTP状态代码
属性
- status:服务器返回的状态代码,如200
- reason:服务器返回的原因短语,如ok
- version:服务器使用的HTTP协议版本
- closed:如果流被关闭是True
- debuglevel:一个调试钩子。如果debuglevel大于零,则在读取和解析响应时将消息打印到stdout
- msg:http.client.HTTPMessage包含响应标头实例,包含reason信息
3.urllib.error(异常处理)
URLError
继承自OSError类,是error异常模块的基类
- reason,即返回错误的原因,reason属性返回的不一定是字符串,也可能是一个对象,例如超时返回socket.timeout类
HTTPError
URLError的子类,专门用来处理HTTP请求错误
- code:返回HTTP状态码
- reason:用于返回错误的原因
- headers:返回请求头
ContentTooShortError(msg, content):不常用
4.urllib.parse(url解析模块)
url解析模块,将url字符串拆分到其组件中,或者将url组件合并到url字符串中,支持file、ftp、gopher、hdl、http、https、imap、mailto、 mms、news、nntp、prospero、rsync、rtsp、rtspu、sftp、 sip、sips、snews、svn、svn+ssh、telnet和wais等协议
urlparse()
实现URL的识别和分段
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
- urlstring:这是必填项,即待解析的URL
- scheme:它是默认的协议(比如http或https等),链接没有带协议信息,会将这个作为默认的协议
- allow_fragments:即是否忽略fragment。如果它被设置为False,fragment部分就会被忽略,它会被解析为path、parameters或者query的一部分,而fragment部分为空
一个标准的连接格式:scheme://netloc/path;parameters?query#fragment,返回结果是一个ParseResult类型的对象,一个6元组,它包含6部分,分别是scheme(协议)、netloc(域名及端口)、path(文件路径)、params(参数)、query(查询组建)和fragment(片段标识符)
urlunparse()
将组建组合为一个url,接受的参数是一个长度为6可迭代对象,返回str类型url
urlsplit()
和urlparse()方法非常相似,不单独解析params这一部分,只返回5个结果。params会合并到path中
urlunsplit()
与urlunparse()类似,长度必须为5
urljoin()
一个base_url(基础链接)作为第一个参数,将新的链接作为第二个参数,该方法会分析base_url的scheme、netloc和path这3个内容并对新链接缺失的部分进行补充,最后返回结果
urlencode()
将字典序列化为GET请求参数(key1=value1&key2=value2形式)
parse_qs()
把一串GET请求参数,转回字典
parse_qsl()
把一串GET请求参数转化为元组组成的列表
quote()
将内容转化为URL编码的格式。URL中带有中文参数时,有时可能会导致乱码的问题,此时用这个方法可以将中文字符转化为URL编码
例如:
keyword = '壁纸'
url = 'https://www.baidu.com/s?wd=' + quote(keyword)
unquote()
进行URL解码
5.urllib.robotparse(robot.txt文件解析模块)
Robots协议
名叫作网络爬虫排除标准(Robots Exclusion Protocol),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取,通常是一个叫作robots.txt的文本文件,一般放在网站的根目录下
User-agent: * # User-agent描述了搜索爬虫的名称,设置为*则代表该协议对任何爬取爬虫有效
Disallow: / # Disallow指定了不允许抓取的目录,设置为/则代表不允许抓取所有页面
Allow: /public/ # Allow一般和Disallow一起使用,用来排除某些限制,这里表示所有页面不允许抓取,但可以抓取public目录
爬虫名称
BaiduSpider:百度;Googlebot:谷歌;360Spider:360搜索;YodaoBot:有道;其它
robotparse
rb = urllib.robotparser.RobotFileParser([robots.txt的url]) # 创键RobotFileParser对象
- set_url():用来设置robots.txt文件的链接
- read():读取robots.txt文件并进行分析,如果不调用这个方法,接下来的判断都会为False
- parse():用来解析robots.txt文件,传入的参数是robots.txt某些行的内容,它会按照robots.txt的语法规则来分析这些内容
- can_fetch():该方法传入两个参数,第一个是User-agent,第二个是要抓取的URL。返回的内容是该搜索引擎是否可以抓取这个URL,返回结果是True或False
- mtime():返回的是上次抓取和分析robots.txt的时间,这对于长时间分析和抓取的搜索爬虫是很有必要的,需要定期检查来抓取最新的robots.txt
- modified():它同样对长时间分析和抓取的搜索爬虫很有帮助,将当前时间设置为上次抓取和分析robots.txt的时间。
例子 :
from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url('http://www.jianshu.com/robots.txt')
rp.read()
#或rp.parse(urlopen('http://www.jianshu.com/robots.txt').read().decode('utf-8').split('\n'))
print(rp.can_fetch('*', 'http://www.jianshu.com/p/b67554025d7d'))