Python爬虫基础的简单了解(1)

urllib的使用

urllib
python内置HTTP请求库,包含四个模块:

  • request:最基本的请求模块 ,用来模拟发送请求。
  • error:异常处理,出现请求错误,可以捕获异常,保证程序不崩溃。
  • parse:工具模块,提供URL的处理方法,合并,拆分等。
  • robotparser:识别机器人协议,判断爬取的规定。

发送请求
使用urllib.request模块,可以模拟一个浏览器发送请求并取得回应。

import urllib.request
response = urllib.request.urlopen(url)
print(response.read().decode('utf-8'))

得到响应后使用read()方法读取其内容,utf-8解码后可以得到内容。

得到的response是一个HTTPResponse类型对象,包含read(), readinto(), getheader(name), getheaders(), fileno()等方法,以及msg, version, status, reason, debuglevel, closed等属性。
status:得到响应的状态码。
getheaders():得到响应头。
getheader(‘Server’):获取响应头中的某一值。


urlopen()除了url以外,还可以传递其他参数
*data:可选参数,添加这个参数后请求方式为POST,data即为要传递的数据,使用bytes()方法将要传递的参数转化为字节流编码格式的内容。

from urllib import request, parse
data = bytes(parse.urlencode({'word': 'hello'}), encoding='utf-8')
response = request.urlopen(url, data=data)
print(response.read())

*timeout
设置超时时间,单位是秒。如果超出请求时间还没有得到响应就抛出异常,如果不指定该参数,使用全局默认时间。

import urllib.request
response = urllib.request.urlopen(url, timeout=1)
print(response.read())

可以利用设置超时时间,跳过抓取长时间未响应的网站。

import socket
from urllib import request, error
 try:
 	response = request.urlopen(url, timeout=1)
 except error.URLError as e:
 	if isintance(e.reason, socket.timeout):
 		print('TIME OUT')

isinstance()类似type(),判断一个对象是否是已知类型,会考虑继承关系,认为子类是一种父类类型。

*其他参数
context:它必须是SSLContext类型,用来指定SSL设置;cafile, capath这俩个参数分别指定CA证书和它的路径,在请求HTTPS链接有用。


Request

urlopen()可以实现最基本的请求,如果要加入更多的信息,可以使用Request类。
依然使用urlopen()发送请求,但是其参数是一个Request类的对象,该对象可以灵活的配置信息,构成一个独立的请求对象。

from urllib import request
request = request.Request(url)
response = request.urlopen(request)
print(response.resd().decode('utf-8'))

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

  • url:请求链接,必填。
  • data:传送的数据,选填,必须是bytes格式,如果是字典,可以用urllib.parse.urlecode()编码。
  • headers:这是一个字典,请求头,常用于修改User-Agent来伪装浏览器,可以直接添加,也可以在后续使用add_header()添加。
  • origin_req_host:请求方的host名称或者IP地址。
  • unverifiable:表示这个请求是否无法验证,默认False,意思就是用户没有权限来选择接受这个请求的结果。
  • method:一串字符串,指定请求的方法,GET, POST等。
from urllib import request, parse
url = 'http://httpbin.org/post'
headers = {
	'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
	'Host': 'httpbin.org'
}
dict = {
	'name': 'Germey'
}
data = bytes(parse.urlencode(dict), encoding='utf-8'))
req = request.Request(url=url, headers=headers, data=data, method='POST')
response = resquest.urlopen(req)
print(response.read().decode('utf-8'))

req = request.Request(url=url, data=data, method=‘POST’)
req.add_header(‘User-Agent’: ‘Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)’)


Handler
各种Handler类似各种处理器,可以处理不同的事情。
urllib.request里面的BaseHandler,是其他所有Handler的父类,提供最基本的方法。
官方文档:https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler

OpenerDirector,成为Opener,urlopen()就是urllib提供的一个Opener,Opener可以实现更高级的功能,深入一层进行配置,使用更底层的实例完成操作。
Opener可以使用open()方法,返回类型和urlopen()一样。

利用Handler来构建Opener

添加代理

from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
#使用proxy_handler添加代理
proxy_handler = ProxyHandler({
	'http': 'http://代理'
	'https': 'https://代理'
})
opener = build_opener(proxy_handler)
try:
	response = opener.open(url)
	print(response.read().decode('utf-8'))
except URLError as e:
	print(e.reason)

这里使用了Proxy_Handler,参数是一个字典,键名是协议类型,键值是代理链接。

Cookies
先将网站的Cookies获取下来:

#导入库
import http.cookiejar, urllib.request
#声明一个CookieJar对象
cookie = http.cookiejar.CookieJar()
#利用HTTPCooikeProcessor构建一个Handler
handler = urllib.request.HTTPCookieProcessor(cookie)
#构建一个opener
opener = urllib.request.build_opener(handler)
#使用opener打开链接
response = opener.open(url)
#将cookies逐条打印出来
for item in response:
	print(item.name+"="+item.value)

结果会输出每条Cookie的名称和值,也可以输出为文件格式。

filename = 'cookies.text'
#声明一个MozillaCookieJar对象
cookie = urllib.cookiejar.MozillaCookieJar(filename)
#构建一个Handler
handler = urllib.request.HTTPCookieProcessor(cookie)
#创建opener()
opener = urllib.request.build_opener(handler)
response = opener.opern(url)
#保存,参数表示忽略丢弃,忽略失效
cookie.save(ignore_discard=True, ignore_expires=True)

声明对象变为MozillaCookieJar,在生成文件的时候会用到,是CookieJar的子类,可以处理Cookies和文件的相关事件。
LWPCookieJar也可以保存和读取Cookies,但是保存格式不是text,而是LWP格式的Cookies文件。

保存之后的读取

cookie = http.cookiejar.LWPCookieJar()
#用load读取
cookie.load('cookies.text', ignore_discard=True, ignore_expires=True)
#使用读取后的cookie建立handler
handler = urllib.request.HTTPCookieProcessor(cookie)
#创建opener
opener = urllib.request.build_opener(handler)
#使用这个opener打开URL,会带上之前的cookie
response = opener.open(url)
print(response.read().decode('utf-8')

参考官方文档:
https://docs.python.org/3/library/urllib.request.html#basehandler-objects

异常处理

  • URLError
    UrlError来自urllib库的error模块,继承自OSError类,是error异常模块的基类,由request模块产生的异常都可以通过捕获这个类来处理
    有一个属性reason,可以返回错误的原因。
from urllib import request, error
try:
	response = request.urlopen(url)
except error.URLError as e:
	print(e.reason)
  • HTTPError
    是URLError的子类,专门处理HTTP请求错误,比如认证失败等,有三个属性:
    code:返回HTTP状态码,比如:404, 200, 500等。
    reason:返回错误原因。
    headers:返回请求头。
    因为HTTPError是URLError的子类,可以先捕获子类的错误,在捕获父类的错误。
from urllib import request, error
try:
	response = request.urlopen(url)
except error.HTTPError as e:
	print(e.reason)
except error.URLError as e:
	print(e.reason)
else:
	print('error')

可以获得更详细的出错信息。

解析链接
urllib.parse.urlparse()
这个方法可以实现URL的识别和分段

from urllib.parse import urlparse
result = urlparse("http://www.baidu.com/index.html;user?id=5#comment")
print(type(result), result)

运行结果:


ParseResult(scheme='http', netloc='www.baidu.com', path='index.html', params='user', query='id=5', fragment='comment')

使用urlparse()将URL拆分为6部分:

  1. scheme:代表协议。
  2. netloc:域名。
  3. path:访问路径。
  4. params:参数。
  5. query:查询条件。
  6. #后面是锚点,用于直接定位页面内部的下拉位置。
    即:scheme://netloc/path;params/?query#fragment
    标准的URL都会符合这个规则,利用urlparse()方法可以拆分.

API用法:
urllib.parse.urlparse(urlstring, scheme=’’, allow_fragment=True)

  • urlstring:待解析的URL
  • scheme:默认的协议,链接如果没有带协议,可以用这个参数指定,如果链接中有协议,又指定了协议,以链接为准。
  • allow_fragment:是否忽略allow_fragment。如果设置为False,fragment会被忽略,归为path、parameters或者query的一部分。

urlunparse()
urlparse的对立方法,接受一个可迭代对象为参数,但是长度必须是6:

from urllib.parse 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

urlsplit()
类似urlparse(),只是不再单独解析params这一部分,值返回5个结果。

urlunsplit()
和urlunparse()类似,也是将链接的各个部分整合在一起,长度为5

urljoin()
也用于生成新链接,提供一个base_url(基础链接)作为第一个参数,新链接为第二个参数,该方法会将base_url的scheme、netloc、path这3个内容并对新连接的缺失部分进行补充,返回结果。

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

结果是:
http://www.baidu.com/FAQ.html
base_url提供三项内容:scheme, netloc, path,新连接中如果没有就补充,如果新连接有,就不变。

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
为了更方便的构造参数,可以事先用字典表示,转为URL参数时,调用这个方法即可。

parse_qs()
反序列化,urlencode()的对立

from urllib.parse import parse_qs
query = 'name=germey&age=22'
print(parse_qs(query))

结果为:
{‘name’: [‘germey’], ‘age’: [‘22’]}

使用parse_qsl()转化为元组的形式
结果为:
[(‘name’: ‘germey’), (‘age’: ‘22’)]
结果是一个列表,里面每一个元素都是一个元组。

quote()
将内容转化为URL编码格式,带有中文参数的时候可能会导致乱码,使用quote()方法,可以将中文也转化为编码格式。

from urllib.parse import quote
keyword = "大熊猫"
url = 'https://www.baidu.com/s?wd=' + quote(keyword)
print(url)

unquote()
quote()方法的对立,可对中文进行解码。

你可能感兴趣的:(python,urllib,简单了解)