IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 第二章爬虫基础之urllib的使用 -> 正文阅读

[Python知识库]第二章爬虫基础之urllib的使用

第二章爬虫基础之urllib的使用

urllib可以实现HTTP请求的发送,还可以把服务器返回的响应转换为python对象。

urllib库包含如下4个模块:

#request:这是最基本的HTTP请求模块,可以模拟请求的发送。就像在浏览器里输入网址然后按下回车一样,只需要给库方法传入URL以及格外的参数,就可以模拟实现发送请求的过程。

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

#parse:一个工具模块。提供了许多URL的处理方法,例如拆分、解析、合并等。

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

  1. 发送请求

urlopen

以Python官网为例,把这个网页抓取下来:

import urllib.request

response = urllib.request.urlopen(‘https://www.python.org’)

print(response.read().decode(‘utf-8’)) ?#输出网页源代码

print(type(response)) ?#输出响应类型

print(response.status) ?#输出响应结果的状态码

print(response.getheaders()) ?#输出响应头信息

print(response.getheaders(‘Server’)) ?#获取响应头中Server的值

响应是一个HTTPResponse类型的对象,主要包含read、readinto、getheader、getheaders、fileno等方法,以及msg、version、status、reason、debuglevel、closed等属性。

data参数

data参数是可选的。在添加该参数时,要用bytes方法将参数转化为字节流编码格式的内容,即bytes类型。如果传递了这个参数,那么它的请求方式就不再是GET,而是POST了。

例:

import urllib.parse
import urllib.request
data = bytes(urllib.parse.urlencode({'name':'germey'}),encoding='utf-8')
response = urllib.request.urlopen('https://www.httpbin.org/post', data = data)
print(response.read().decode('utf-8'))

这里传递了一个参数name,值是germey,需要将它转码成bytes类型。转码时采用了bytes方法,该方法的第一个参数得是str类型,因此用urllib.parser模块里的urlencode方法将字典参数转化为字符串;第二个参数用于指定编码格式,这里指定为utf-8。请求站点是www.httpbin.org,它可以提供HTTP请求测试。本次请求的URL为https://www.httpbin.org/post,这个链接可以用来测试POST请求,能够输出请求的一些信息,其中就包含传递的data参数。输出包含传递的参数,出现在form字段中,这表明是模拟表单提交,以POST方式传输数据。

timeout参数

timeout参数用于设置超时时间,单位为秒,意思是如果请求超出了设置的这个时间,还没有得到相应,就会抛出异常。

例:

import urllib.request
response = urllib.request.urlopen('http://www.httpbin.org/get',timeout=0.1)
print(response.read())

结果抛出URLError异常,错误原因是超时。

可以通过设置这个超时时间,实现当一个网页长时间未相应时,就跳过对它的抓取。此外,利用try except也可以实现,例:

try:
????response = urllib.request.urlopen('http://www.httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:
????if isinstance(e.reason, socket.timeout):
????????print('TIME OUT')

这里捕获到URLError这个异常,并判断异常类型是socket.timeout超时异常,因此得出确实是因为超时而报错的结论,打印输出TIME OUT。

Request

如果需要往请求中加入Headers等信息,就得利用更强大的Request类来构建请求了。

例:

from urllib import request,parse
url = 'https://www.httpbin.org/post'
headers = {
????'User-Agent': 'Mozilla/4.0(compatible; MSIE 5.5; windows NT',
????'Host': 'www.httpbin.org'
}
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'))

高级用法

对于一些更高级的操作(例如Cookie处理、代理设置等),需要用到Handler.urllib.request模块里的BaseHandler类是其他所有Handler类的父类,提供了例如default_open、protocol_request等最基本的方法。

举例几个继承BaseHandler类的子类:

#HTTPDefaultErrorHandler用于处理HTTP响应错误,所有错误都会抛出HTTPError类型的异常。

#HTTPRedirectHandler用于处理重定向。

#HTTPCookieProcessor用于处理Cookie。

#ProxyHandler用于设置代理,代理默认为空。

#HTTPPasswordMgr用于管理密码,它维护着用户名密码的对照表。

#HTTPBasicAuthHandler用于管理认证,如果一个链接在打开时需要认证,那么可以用这个类来解决认证问题。

urllib的Opener类可以实现更高级的功能,利用Handler类来构建Opener类。

验证

例:

from urllib.request import HTTPBasicAuthHandler,HTTPPasswordMgrWithDefaultRealm,build_opener
from urllib.error import URLError
username = 'admin'
password = 'admin'
url = 'https://ssr3.scrape.center/'
p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username,password)
auth_handler = HTTPBasicAuthHandler(p)
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)

代理

from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy_handler = ProxyHandler({
????'http': 'http://127.0.0.1:8080',
????'http': 'https://127.0.0.1:8080'
})
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
filename = 'cookie.txt'
#cookie = http.cookiejar.CookieJar()
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('https://www.baidu.com')
for item in cookie:
????print(item.name + '=' + item.value)
cookie.save(ignore_discard=True, ignore_expires=True) ??#保存cookie文件

  1. 处理异常

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

URLERROR

URLERROR类来自urllib库的error模块,继承自OSError类,是error异常模块的基类,由request模块产生的异常都可以通过捕获这个类来处理。它具有一个属性reason,即返回错误原因。

from urllib import request, error
try:
????response = request.urlopen('https://nosuchurl.com/404')
except error.HTTPError as e:
????print(e.reason, e.code, e.headers, sep = '\n')
except error.URLError as e:
????print(e.reason)
else:
????print('Request Successsfully')

URLError是HTTPError的父类,所以可以先选择捕获子类的错误,再捕获父类的错误。

3、解析链接

urllib库提供了parse模块,这个模块定义了处理URL的标准接口,例如实现URL各部分的抽取

合并以及链路转换。

urlparse

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

from urllib.parse import urlparse

result = urlparse('https://www.baidu.com/index.html;user?id=5#comment')

print(type(result))

print(result)

urlparse方法在解析URL时有特定的分隔符。具体如下:

scheme://netloc/path;parse?query#fragment

urlparse的API用法:

urllib.parse.urlparse(urlstring, scheme=’’,allow_fragments=True)

urlstring:待解析的URL。

scheme:假如待解析的URL不带协议信息,可以在这里指明。

allow_fragments:是否忽略fragment。如果此项设置为False,哪门fragment部分就会被忽略,它会被解析为path、params或query的一部分,而fragment部分为空。

例:

from urllib.parse import urlparse
result = urlparse('https://www.baidu.com/index.html;user?id=5#comment', allow_fragments=False)
print(result)

运行结果ParseResult实际上是一个元祖,既可以用属性名获取其内容,也可以用索引来顺序获取。例:

from urllib.parse import urlparse
result = urlparse('https://www.baidu.com/index.html#comment', allow_fragments = False)
print(result.scheme, result[0], result.netloc, result[1], sep='\n')

可以发现result.scheme和result[0],result.netloc和result[1]的结果一致。

urlunparse

urlunparse用来构造url。这个方法接收的参数是一个可迭代的对象,长度必须是6,否则会抛出参数数量问题。例:

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

urlsplit

该方法和urlparse类似,只不过不再单独解析params这一部分,返回5个结果。例:

from urllib.parse import urlsplit
result = urlsplit('https://www.baidu.com/index.html;user?id=5#comment')
print(result.scheme,result[0])

urlunsplit

与urlunparse类似。也是将链接各个部分组合成链接的方法,唯一区别是参数的长度必须为5。例:

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

urljoin

我们可以提供一个base_url(基础链接)作为该方法的第一个参数,讲过新的链接作为第二个参数。urljoin方法会分析base_url的scheme、netloc和path这3个内容,并对新链接缺失的部分进行补充,最后返回结果。例:

from urllib.parse import urljoin
print(urljoin('https://www.baidu.com', 'FAQ.html'))
print(urljoin('https://www.baidu.co', 'https://test.com/FAQ.html'))
print(urljoin('https://www.baidu.com/about.com', 'https://test.com/FAQ.html?question=2'))
print(urljoin('https://www.baidu.com?wd=abc', 'https://test.com/index.php'))
print(urljoin('https://www.baidu.com', '?category=2#commit'))
print(urljoin('www.baidu.com', '?category=2#commit'))
print(urljoin('www.baidu.com#comment', '?category=2'))

运行结果如下:

https://www.baidu.com/FAQ.html

https://test.com/FAQ.html

https://test.com/FAQ.html?question=2

https://test.com/index.php

https://www.baidu.com?category=2#commit

www.baidu.com?category=2#commit

www.baidu.com?category=2

可以发现base_url提供了三项内容:scheme、netloc和path。如果新的链接不存在这三项,就予以补充;如果存在,就使用新的链接里面的,base_url中的是不起作用的。

urlencode

例:

from urllib.parse import urlencode
params = {'name':'germey','age':25}
base_url = 'https://www.baidu.com?'
url = base_url + urlencode(params)
print(url)

首先申明一个字典params,用于将参数表示出来,然后调用urlencode方法将params序列化为GET请求的参数。

parse_qs

利用parse_qs方法,可以将一串GET请求参数转回字典,例:

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

parse_qsl

parse_qsl方法将参数转化为由元祖组成的列表,例:

from urllib.parse import parse_qsl
query = 'name=germey&age=25'
print(parse_qsl(query))

quote

该方法可以将内容转化为URL编码的格式。当URL中带有中文参数时,有可能导致乱码问题,此时用quote方法可以将中文字符转化为URL编码,例:

from urllib.parse import quote
keyword = '壁纸'
url = 'https://www.baidu.com/s?wd='+quote(keyword)
print(url)

unquote

unquote方法可以进行URL解码,例:

from urllib.parse import unquote
url = 'https://www.baidu.com/s?wd=%E5%A3%81%E7%BA%B8'
print(unquote(url))

4、分析Robots协议

利用urllib库的robotparser模块,可以分析网站的Robots协议。

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

看一个robots.txt的例子:

User-agent: *

Disallow: /

Allow: /public/

这限定了所有搜索爬虫只能爬取public目录。将上述内容保存成robots.txt文件,放在网站的根目录下,和网站的入口文件放在一起。

User-agent描述了搜索爬虫的名称,这里将其设置为*,代表Robots协议对所有爬取爬虫都有效。

Disallow指定了不允许爬虫爬取的目录,上例设置为/,代表不允许爬取所有页面。

Allow一般会和Disallow一起用,用来排除某些限制。上例设置为/public/,结合Disallow的设置,表示所有页面都不允许爬取,但可以爬取public目录。

robotparser

可以使用robotparser模块来解析robots.txt文件。该模块提供了一个类RobotFileParser,它可以根据某网站的robots.txt文件判断一个爬取爬虫是否有权限爬取这个网页。

RobotFileParser类的几个常用方法如下:

set_url:用来设置robots.txt文件的链接。如果在创建RobotFileParser对象时传入了链接,就不需要使用这个方法设置了。

read:读取robots.txt文件并进行分析。这个方法执行读取和分析操作,一定要执行。

parse:用来解析robots.txt文件,传入其中的参数是robots.txt文件中某些行的内容,它会按照robots.txt的语法规则来分析这些内容。

can_fetch:该方法有两个参数,第一个是User-Agent,第二个是要抓取的URL。返回结果是True或False,表示User-Agent指示的搜索引擎是否可以抓取这个URL。

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

modifie:它同样对长时间分析和抓取的搜索爬虫很有帮助,可以将当前时间设置为上次抓取和分析robots.txt文件的时间。例:

from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url('https://www.baidu.com/robots.txt')
rp.read()
print(rp.can_fetch('Baiduspider','https://www.baidu.com'))
print(rp.can_fetch('Baiduspider','https://www.baidu.com/homepage/'))
print(rp.can_fetch('Googlebot','https://www.baidu.com/homepage/'))

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 22:52:51  更:2021-12-28 22:55:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 3:31:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码