使用urllib
urllib是python内置的HTTP请求库,包含四个模块:
- request : 是最基本的HTTP请求模块,可以用来模拟发送请求
- error: 异常处理模块,如果出现请求错误,我们可以捕获这些异常,然后进行重试或其他操作,保证程序不会意外终止
- parse: 一个工具魔魁啊,提供了许多URL处理方法,比如拆分、解析、合并等
- robot parser : 主要用于识别网站的robots.txt文件,然后判断哪些网站可以爬
发送请求
urlopen()方法
url lib.request 模块提供了最基本的构造HTTP请求方法,利用它可以模拟浏览器的一个请求发起过程,同时带有处理授权验证(authentication)、重定向(redirection)、浏览器Cookies以及其他内容
import urllib.request
response= urllib.request.urlopen('https://www.baidu.com')
print(response.read().decode('utf-8'))
以上代码利用最基本的urlopen()方法,可以完成最基本的网页GET请求。
当然可以传递其他内容,如下为urlopen()函数的API:
urllib.request.urlopen(url,date=None,[timeout,]*,cafile=None,capath=None,cadefaule=False,context=None)
- date参数
是可选择的,如果添加该参数,并且如果它是字节流编码格式的内容,即bytes类型,则需要通过bytes()方法转化。当然,如果传递了这个参数,则它的请求方式不再是GET方式,而是POST方式。
import urllib.parse
import urllib.request
data=bytes(urllib.parse.urlencode({'world':'hello'}),encoding='utf8')
response=urllib.request.urlopen('https://www.baidu.com'.data=data)
print(pesponse.read())
解析:
传递了一个参数word,值是hello。它需要被转码成bytes(字节流)类型。其中转字节流采用bytes()方法,该方法第一个参数需要时str(字符串)类型,需要urllib.prase模块里的urlencode()方法将参数字典转化为字符串;
第二个参数制定了编码格式,这里制定为utf8
-
timeout参数
用于设置超时时间,单位为秒。如果不制定该参数,就会使用全局默认时间 -
其他参数
除了data、timeout参数外,话语context参数,它必须是ssl.SSLContext类型,用来制定SSL设置。
cafile和capath这两个参数用来分别指定CA证书和它的路径。
Request类
urlopen()方法可以实现最基本的请求发起,但不足以构建一个完整的请求。比如请求中添加Headers等信息,就可以利用更强大的Request类来构建。
import urllib.request
request = urllib.request.Request('http:python.org')
response = urllib.request.urlopen(ruquest)
print(response.read().decode('utf-8'))
解析:依然使用urlopen()方法发送请求,但该方法的参数不再是URL,而是一个Request类型的对象。通过构造这个数据姐毮股,一方面可以将请求独立成一个对象,另一方面可更加丰富和灵活地配置参数。
Request参数构造方法:
class urllib.request.Request(url,data=None,headers={},origin_reqhost=None,unverifiable=false,method=None)
- 第一个参数url,用于请求URL,这是必传参数,其他的都是可选参数
- 第二个参数data,如果要传必须是bytes(字节流)类型的。如果它是字典,可以先用urllib.parse模块里的urlencode()编码
- 第三个参数headers是一个字典,它是请求头,我们可以子啊构造请求时通过headers参数直接构造,也可以通过调用请求实力的add_header()方法添加
- 第四个参数origin_req_host指的是请求方的host名称或者IP地址
- 第五个参数unverifiable比哦啊是这个请求是否无法验证,默认是False,意思是用户没有足够的权限来选择接受这个请求的结果
- 第六个参数method是一个字符串,用来指示请求使用的方法,比如GET、POST和PUT等
处理异常
urllib的error模块定义了由request模块产生的异常。
URLError
URLError继承自自OSError,是error异常模块的基类,由request模块生的异常都可以通过补货这个类来处理。它具有reason属性,可以返回错误原因。
HTTPError
它是URLError的子类,专门用来处理HTTP请求错误。它具有3个属性
- code:返回HTTP状态码,如404表示页面不存在
- reason:同父类一样,用于返回错误原因
- headers:返回请求头
from urllib import request,error
try:
reaponse=request.urlopen('http://baidu.com')
except error.HTTPError as e:
print (e.reason,e.code,e.headers)
解析链接
parse模块,定义了处理URL的标准接口,例如实现URL个部分的抽取、合并以及链接转换。
1、urlparse()
该方法实现了URL的识别和分段
from urllib.parse import urlparse
result = urlparse('http:www.baidu.com')
print(type(result),result)
运行结果:
<class 'urllib.parse.ParseResult'>
ParseResult(scheme='http', netloc='', path='www.baidu.com', params='', query='', fragment='')
解析:返回的结果是一个ParseResult类型的对象,包含了6个部分,分别是sheme 、netloc、path、params、query和fragment
sheme - 协议
netloc-域名
path-访问路径
params-代表参数
query-查询条件
fragment-锚点,用于直接定位页面内部的下拉位置
即:http://www.netloc/path;params?query#fragment
2、urlunparse()
它接受的参数是一个可迭代对象,但是它的长度必须是6,否则会跑出参数数量不足或者过多的问题
from urllib.prase import urlunparse
data=['http','www.baidu.com','index.html','user','a=6','comment']
print(urlunparse(data))
运行结果:
http://www.baidu.com.index.html;user?a=6#comment
3、urlsplit()
和 urlparse()非常类似,但它不在单独分析params这一部分,只返回5个结果。path会合并到path中。
4、urlunsplit()
与urlunparse()非常类似,唯一的区别是传入的参数长度必须是5
5、urljoin()
urlunparse()和 urlunsplit ()都可以完成链接合并,但前提必须是有特定长度的对象,链接的每一部分都要清晰分开。
所以另一种方法,就是urljoin()方法。我们可以提供一个base_url(基础链接)作为第一个参数,将新链接作为第二个参数,该方法会分析base_url的scheme、netloc和path这三个内容对链接缺失的部分进行补充
6、urlencode()
它在构造GET请求参数的时候非常有用
from urllib.parse import urlencode
params={
'name':'germey',
'age':22
}
base_url='http://www.baidu.com?'
url=base_url+urlencode(params)
print(url)
运行结果:
http://www.baidu.com?name=germey&age=22
分析:这里首先声明了一个字典将参数表示出来,然后调用urlencode()方法将其序列化GET请求参数
7、parse_qs()
反序列化,利用parse_qs()方法就可以将GET请求参数转回字典
from urllib.parse import parse_qs
query='name=germy&age=22'
print(parse_qs(query))
运行结果:
{'name':['germey'],'age':['22']}
8、parse_qsl()
它用于将参数转化为原则组成的列表
from urllib.parse import parse_qsl
query='name=germy&age=22'
print(parse_qsl(query))
运行结果:
[('name','germey'),('age','22')]
9、quote()
该方法可以将内容转化为URL编码格式。当URL中带有中文时候,有可能回导致乱码问题,此时可以用这个方法
from urllib.parse import quote
keyword='壁纸'
url='https://www.baidu.com/s?wd='+quote(keyword)
print(url)
运行结果:
https://www.baidu.com/s?wd=%E5%A3%E7%BA%B8
10、unquote()
该方法进行URL解码
from urllib.parse import unquote
url='https://www.baidu.com/s?wd=%E5%A3%E7%BA%B8'
print(unquote(url))
运行结果:
https://www.baidu.com/s?wd=壁纸
分析Robots协议
Robots协议夜称作爬虫协议、机器人协议,全名网络爬虫排除标准。用来告诉爬虫和搜索引擎哪些页面可以抓取哪些不可以抓取。它通常是一个叫做robots.txt的文本文件,一般放在网站根目录下。
使用robotparser模块解析robots.txt。该模块提供了一个类RobotFileParser,它可以根据网站robots.txt文件来判断一个爬取爬虫是否有权限来爬去这个网页。使用时只需要在构造方法里传入robots.txt的链接即可:
url lib.robotparser.RobotFileParser(url='')
- set_url(): 用来设置robots.txt文件的链接。如果在叉棍见RobotFileParser对象时传入了链接,那么就不需要再使用这个方法设置了
- read():读取robots.txt文件并进行分析。这个方法不会返回任何内容,但是执行了读取操作。
- parse():用来解析robots.txt文件,传入的参数时robots.txt某些行的内容,它会按照robots.txt的语法规则来分析这些内容
- can_fetch():该方法传入俩个参数,User-agent和URL。返回的内容是该搜索引擎是否可以抓取这个URL,返回的结果是True和False
- mtime():返回的是上次抓取和分析robots.txt的时间
- modified():将当前时间设置为上次住去和分析robots.txt的时间
from urllib.robotparser import RobotFileParser
rp=RobotFileParser()
rp.set_url('http://www.jianshu.com/robots.txt')
rp.read()
print(rp.can_fetch('*','http://www.jianshu.com/p/b67554025d7d'))
print(rp.can_fetch('*',"http://www.jianshu.com/search?q=python&page=1&type=cllections"))
运行结果:
True
False