分享

使用urllib

 印度阿三17 2019-07-30

urllib库是Python内置的HTTP请求库,包含4个模块

1)request:它是最基本的HTTP请求模板,可以用来模拟发送请求

2)error:异常处理模块,如果出现请求错误,我们可以捕获这些异常,然后可以进行重试或其他操作来保证程序不会意外终止

3)parse:一个工具模块,提供许多URL处理方法,如拆分,解析合并等

4)robotparser:主要用来识别网站的robots.txt文件,然后判断哪些网站可以爬,哪些网站不可以爬

一.发送请求

使用urllib的request模块,可以方便地实现请求的发送并得到响应

1)urlopen()

urlopen()方法除了第一个参数可以传递URL外,还可以传递其他内容,比如data,timeout等

A.data参数

data参数是可选的。如果要添加该参数,并且如果它是字节流编码格式的内容,即bytes类型,则需要通过bytes()方法转化。如果传递了这个参数,则它的请求方式不再是GET方式,而是POST方式

B.timeout参数

timeout参数用于设置超时时间,单位为秒,如果请求超出了设置时间,还没有得到响应,就会抛出异常,如果不知道该参数,就会使用全局默认时间,它支持HTTP,HTTPS,FTP请求

C.其他参数

context参数,它是必须是ssl.SSLContext类型用来指定SSL设置

此外,cafile和capath这两个参数用来指定CA证书和他的路径,这个在请求HTTPS链接时有用

 2)Request

urlopen()方法可以实现最基本请求的发起,但其简单的参数并不足以构建一个完整的请求,如果需要在请求中/加入Headers等信息,则需要利用强大的Request来构建

Request参数构造方法

1)第一个参数url用于请求URL,这是必传参数,其他都是可选参数
2)第二个参数data如果要传,必须传bytes(字节流)类型的,如果它是字典,可以先用urllib。parse模块里的urlencode()编码
3)第三个参数headers是一个字典,它就是请求头,可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add_header()方法调用
4)第四个参数origin_req_host指的是请求方的host名称或者IP地址
5)第五个参数unverifiable表示这个请求是否是无法验证的,默认为false,意思是用户没有足够的权限来选择接收这个请求的结果
6)第六个参数method是一个字符串,用来指示请求使用的方法,如GET,POST和PUT等
from urllib import request,parse
url="http:///post"
headers={
    'User-Agent':'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)',
    'Host':''
}
dict={
    'name':'Germey'
}
data=bytes(parse.urlencode(dict),encoding='utf-8')
req=request.Request(url=url,data=data,headers=headers,method='POST')
response=request.urlopen(req)
print(response.read().decode("utf-8"))

3)高级用法

对于一些高级操作,如Cookies处理,代理设置等,就要用到Handler,可以把它理解为各种处理器,有专门处理登录验证的,有处理Cookies的,有处理代理设置的

urllib.request模块里的BaseHandler类是所有其他Handler的父类,它提供了最基本的方法

下面是各种Handler子类继承这个BaseHandler类

1)HTTPDefaultErroeHandler: 用于处理HTTP响应错误,错误都会抛出HTTPError类型的异常
2)HTTPRedirectHandler: 用于处理重定向
3)HTTPCookieProcessor: 用于处理Cookies
4)ProxyHandler:用于设置代理,默认代理为空
5)HTTPPasswordMgr:用于管理密码,它维护了用户名和密码的表
6)HTTPBasicAuthHandler:用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题

另外一个比较重要的类是OpenerDirector,我们可以称为Opener,之前用过的urlopen()实际上就是urllib为我们提供的一个Opener

我们需要实现更高级的功能,所以需要深入一层进行配置,使用更底层的实例来完成操作,所以就用到Opener,Opener可以使用open()方法,返回类型和urlopen()一样

利用Hanler来构建Opener

用法:

A.验证

有些网站需要输入用户名和密码,验证成功后才能查看页面,要请求这样的页面,需要借助HTTPBasicAuthHandler就可以完成

from urllib.request import HTTPPasswordWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError
username='username'
password='password'
url='http://localhost:5000/'
p=HTTPPasswordWithDefaultRealm()
p.add_passsword(None,url,username,password)
auth_handler=HTTPBasicAuthHandler(p)
opener=built_opener(auth_handler)
try:
result=opener.open(url)
html=result.read().decode('utf-8')
print(html)
except URLError as e:
print(e.reason)

B.代理

在做爬虫时,如果要添加代理,可以这样做

from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener
proxy_handler =ProxyHandler({
'http':'http://127.0.0.1:9743',
'https':'https://127.0.0.1:9743'
})
opener=build_opener(proxy_handler)
try:
response=opener.open('https://www.baidu.com')
print(resposne.read().decode("urtf-8"))
except URLError as e:
print(e.reason)

使用ProxyHandler,其参数是一个字典,键名是协议类型(如HTTP或HTTTPS),键值是代理链接,可以添加多个代理

C.Cookies

Cookies的处理就需要相关的Handler

from urllib.request import HTTPCookieProcessor,build_opener
import http.cookiejar
cookie=http.cookiejar.CookieJar()
handler=HTTPCookieProcessor(cookie)
opener=build_opener(handler)
response=opener.open("https://www.baidu.com")
for i in cookie:
    print(i.name '=' i.value)

这样可以看到每条Cookie的名称和值

将cookie以文本形式保存代码如下

import http.cookiejar,urllib.request
filename='Cookies.text'
cookie=http.cookiejar.MozillaCookieJar(filename)
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open("https://www.baidu.com")
cookie.save(ignore_discard=True,ignore_expires=True)

MozillaCookieJar才生成文件时会用到,时CookieJar的子类。可以用来处理Cookies和文件相关的事件,比如读取和保存Cookies,可以将Cookies保存成Mozilla型浏览器的Cookies格式

LWPCookieJar也可以读取和保存Cookies,但是保存的格式和MozillaCookieJar的不一样,它会保存成libwww-perl(LWP)格式的Cookies文件

从文件中读取:

import http.cookiejar,urllib.request
cookie=http.cookiejar.MozillaCookieJar()
cookie.load('Cookies.txt',ignore_discard=True,ignore_expires=True)
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open("https://www.baidu.com")
print(response.read().decode('utf-8'))

 

二.处理异常

urllib的error模块定义了由request模块产生的异常。如果出现了问题,request模块便会抛出error中定义的异常

A.URLError

URLError类来自urllib库的error模块,它继承自OSError类,是error异常模块的基类,有request模块生的异常都可以通过这个类来处理

from urllib import request,error
try:
    response=request.urlopen("https://www.")
except error.URLError as e:
    print(e.reason)

B.HTTPError

它是URLError的子类,专门用来处理HTTP请求错误,比如认证请求失败,它有三个属性

1)code:返回HTTP状态码,比如404表示网页不存在,500表示服务器内部错误
2)reason:同父类一样,用于返回错误的原因
3)headers:返回请求头
from urllib import request,error
try:
    response=request.urlopen("https:///index.htm")
except error.HTTPError as e:
    print(e.code,e.reason,e.headers)

 

三.解析链接

urllib库还提供了parse模块,它定义了处理URL的标准接口,例如实现URL各部分的抽取,合并以及链接转换

1)urlparse

该方法可以实现URL的识别和分段

from urllib.parse import urlparse
result=urlparse("https://www.dengwenxiong/index.html;user?id=5#comment")
print(result)
ParseResult(scheme='https', netloc='www.dengwenxiong', path='/index.html', params='user', query='id=5', fragment='comment')

其将url分为6部分scheme表示协议,netloc表示域名,path表示访问路径,params表示参数,query表示查询条件,fragment表示锚点,用于直接定位页面内部的下拉位置

urlparse()有三个参数:urlstring,scheme和allow_fragments

uslstring是必填项,即待解析的URL

scheme:它是默认的协议,假如链接没有协议,会将这个作为默认的协议

allow_fragments:即是否忽略fragment,如果它被设置为false,fragment部分被忽略,它会被解析成path,parameters或者query的一部分,而fragment部分为空

2)urlunparse

它接受的参数是一个可迭代对象,但是它的长度必须是6,否则会抛出参数数量不足或者过多的问题

from urllib.parse import urlunparse
data=('https','www.baidu.com','index.html','user','a=6','comment')
print(urlunparse(data))

3)urlsplit()

这个方法和urlparse()方法非常相似,只不过它不在单独解析params这一部分,只返回5个结果,params会合并到path中,可以用属性获取值,也可以用索引来获取

4)urlunsplit()

与urlunparse()类似,也是将链接各个部分组合成完整链接的方法,传入的参数也是一个可迭代对象,唯一的区别是长度必须为5

5)urljoin()

生成链接除了上面两个方法,还有就是urljoin()方法,可以提供一个base_url(基础链接)作为第一个参数,将新的链接作为第二个参数,该方法会分析base_url的scheme,netloc和path这三个内容并对新链接缺失的部分进行补充

base_url提供三项内容scheme,netloc和path,如果这3项在新的链接里不存在,就予以补充,如果新的链接存在,就使用新的链接的部分,而base_url中的params,query和fragment是不起作用的

from urllib.parse import urljoin
print(urljoin('http://www.baidu.com','FAQ.html'))

6)urlencode()

它在构造get请求参数的时候非常有用

from urllib.parse import urlencode
params={
    'name':'dwx',
    'age':22
}
base_url='http://www.baidu.com?'
url=base_url urlencode(params)
print(url)

 7)parse_qs()

有了序列化就要有反序列化,如果有一串GET请求参数,利用parse_qs()方法能将其转回字典

from urllib.parse import parse_qs
query="name=dengwenxiong&age=22"
print(parse_qs(query))

8)parse_qsl()

它用于将参数转化为元组组成的列表

9)quote()

该方法可以将内容转化为URL格式

from urllib.parse import quote
key="邓文雄"
url="http://www.baidu.com/s?wd=" quote(key)
print(url)

10)unquote()

可以对URL进行解码

from urllib.parse import unquote
key="邓文雄"
print(unquote(key))

 

三.分析Robots协议

利用urllib的robotparser模块,我们可以实现网站Robots协议的分析

1)Robots协议

Robots协议也称为爬虫协议,机器人协议,全名为网络爬虫排除标准(Robots Exclusion Protocol),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些页面不可抓取。它通常是一个叫作robots.txt的文本文件,一般放在网站的根目录下。

当搜索爬虫访问一个站点时,它会首先检查这。个站点根目录下是否存在robots.txt文件,如果存在,搜索爬虫会根据其中定义的爬取范围来爬取,如果没有找到这个文件,搜索爬虫便会访问所以可直接访问的页面

下面是一个robot.txt的样例

A.对所有搜索爬虫只允许爬取public目录

User-agent:*
Disallow:/
Allow:/public/

User-agent描述了搜索爬虫的名称,这里设置为*则代表该协议对任何爬取爬虫有效

Disallow指定了不允许抓取的目录,设置为/则代表不允许抓取所有页面

Allow一般和Disallow一起使用,一般不会单独使用,用来排除某些限制,这里设置为/public/则表示所有页面不允许抓取,但可以抓取public目录

B.禁止所有爬虫访问任何目录

User-agent:*
Disallow:/

C.允许所有爬虫访问任何目录

User-agent:*
Disallow:

D.禁止所有爬虫访问网站某些目录

User-agent:*
Disallow:/private/
Disallow:/tmp/

E.只允许某一个爬虫访问

User-agent:WebCrawler
Disallow:
User-agent:*
Disallow:/

2)爬虫名称

一些常见搜索爬虫的名称即其对应的网站

爬虫名称 名称 网站
BaiduSpider 百度 www.baidu.com
Googlebor 谷歌 www.google.com
360Spider 360搜索 www.so.com
YodaoBor 有道 www.youdao.com
ia_archiver Alexa www.alexa.cn
Scooter altavista www.altavista.com

3)robotparser

可以用robotparser模块来解析robots.txt;该模块提供了一个类RobotFileParser,它可以根据某网站的robots.txt文件来判断一个爬取爬虫是否有权限来爬取这个网页;这个类用起来非常简单,只需要在构造方法里传入robots.txt的链接即可,其声明如下:

urllib.robotparser.RobotFileParser(url=' ')

也可以在声明时不传入,默认为空,使用set_url()方法设置也行;

这个类常用的几个方法:

1)set_url():用来设置robots.txt文件的链接。如果在创建RobotFileParser对象时传入了链接,那么就不需要再使用这个方法设置了
2)read():读取robots.txt文件并进行分析,这个方法执行一个读取和分析操作,如果不调用这个方法,接下来的判断都会为false,所以一定要调用这个方法,这个方法不返回任何内容,但是执行了读取操作
3)parse():用来解析robots.txt文件,传入的参数是robots.txt某些行的内容,它会按照robots.txt的语法规则来分析这些内容
4)can_fetch():该方法传入两个参数,第一个是User-agent,第二个是要抓取的URL。返回的内容是该搜索引擎是否可以抓取这个URL,返回的结果是True或False
5)mtime():返回的是上次抓取和分析robots.txt的时间,这对于长时间分析和抓取的搜索爬虫是很有必要的,你可能需要定期检查来抓取最新的robots.txt
6)modified():它对长时间分析和抓取的搜索爬虫很有帮助,将当前时间设置为上次抓取和分析robots.txt的时间
from urllib.robotparser import RobotFileParser
rp=RobotFileParser()
rp.set_url('http://www.jianshu.com/robots.txt')
rp.read()#也可用parse()读取和分析rp.parse(urlopen('http://www.jianshu.com/robots.txt').read().decode('utf-8').split('\n'))
print(rp.can_fetch('*','http://www.jianshu.com/'))

 

来源:https://www./content-4-369601.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多