Python网络爬虫(一) | urllib包基本使用教程

在这里插入图片描述

urllib包 介绍

urllib 是Python内置的一个软件包,包里面包含了以下几个用来处理 url 的模块:

  • urllib.request: 用于打开和阅读URL,以用它来模拟发送请求,就像在浏览器里输入网址然后敲击回车一样,获取网页响应内容。
  • urllib.error : 包含由引发的异常 urllib.request
  • urllib.parse: 用于解析URL
  • urllib.robotparser: 用于解析robots.txt文件,判断网站是否能够进行爬取。
    掌握以上四个模块,大致就能对网页进行简单的爬虫操作。

1、urllib.request 模块

该urllib.request模块定义了有助于在复杂环境中打开URL(主要是HTTP)的函数和类-基本身份验证和摘要身份验证,重定向,Cookie等。

1.1 urllib.request.urlopen()

该功能主要用于模拟网站请求,返回一个 HTTPResponse 类型的对象。

函数语法:

urllib.request.urlopen(url,data = None[ timeout,] *,cafile = None,capath = None,cadefault = False,context = None

参数说明:

  • url: 必选参数,是一个 str 字符串或者 Request 对象
  • data: bytes 类型的可选参数,如果传递的是字典型数据,可以用 urllib.parse.urlencode()进行编码,返回 str 字符串,再将 str 转换成 bytes 字节流。如果传递 data 参数,urlopen 将使用 HTTP POST 方式请求,否则为 HTTP GET 请求。
  • timeout: 可选参数,设置超时时间(未设置时使用全局默认超时时间),以秒为单位计时,如果 urlopen 请求超出了设置时间还未得到响应则抛出异常。
  • cafile 和 capath: 可选参数,在 HTTPS 连接请求时指定已认证的 CA 证书以及证书路径。
  • cadefault: 一般可忽略该参数。
  • context: ssl.SSLContext 类型的可选参数,用来指定 SSL 设置。

返回类型:
urlopen 函数请求返回一个 HTTPResponse 响应上下文,一般有如下属性:

  • geturl(): 返回所获取资源的URL,通常用于确定是否遵循了重定向
  • info(): 以email.message_from_string()实例的形式返回页面的元信息
  • getcode(): 返回HTTPResponse 响应的状态码。

常用方法属性:

response=urllib.request.urlopen('https://www.python.org')  #请求站点获得一个HTTPResponse对象
#print(response.read().decode('utf-8'))   #返回网页内容
#print(response.getheader('server')) #返回响应头中的server值
#print(response.getheaders()) #以列表元祖对的形式返回响应头信息
#print(response.fileno()) #返回文件描述符
#print(response.version)  #返回版本信息
#print(response.status)  #返回状态码200,404代表网页未找到
#print(response.debuglevel) #返回调试等级
#print(response.closed)  #返回对象是否关闭布尔值
#print(response.geturl()) #返回检索的URL
#print(response.info()) #返回网页的头信息
#print(response.getcode()) #返回响应的HTTP状态码
#print(response.msg)  #访问成功则返回ok
#print(response.reason) #返回状态信息

1.2 urlopen函数实例:

实例一:

# 创建一个 HTTP GET 请求,输出响应上下文
from urllib.request import urlopen
response = urlopen("http://www.python.org")
print(response.read())

实例二:

# 创建一个 HTTP POST 请求,输出响应上下文
from urllib.request import urlopen
from urllib.parse import urlencode
data = {
    
    'kw' : 'python'}
data = bytes(urlencode(data), encoding = 'utf-8')
response = urlopen("https://docs.python.org/3/library/urllib.request.html", data)
print(response.read().decode('unicode_escape'))

实例三:

# 创建一个 HTTP GET 请求,设置超时时间为0.5s
import urllib.request
import urllib.error
try:
    response=urllib.request.urlopen('http://www.python.org',timeout=0.5)
    print(response.read()) 
except urllib.error.URLError as e:
    print(e.reason)

2.1 urllib.request.Request()

该函数主要用于构造一个 url,返回一个 urllib.request.Request 对象。

函数语法:

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

参数说明:

  • url: 必选参数,请求的 url 地址。
  • data: bytes 类型的可选参数。
  • headers: 字典类型,有些 HTTP 服务器仅允许来自浏览器的请求,因此通过 headers 来模拟浏览器对 url 的访问,比如模拟谷歌浏览器时使用的 headers:“Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36”。可以通过调用 add_header() 来添加 headers 信息。
  • origin_req_host: 请求方的 host 名称或者 IP 地址。
  • unverifiable: 表示这个请求是否无法验证,默认为 False。比如请求一张图片,如果没有权限获取图片那它的值就是 true。
  • method: 是一个字符串,用来指示请求使用的方法,如:GET,POST,PUT 等,默认是 GET 请求。

返回类型:
返回一个 HTTPResponse 响应上下文。

  • geturl(): 返回所获取资源的URL,通常用于确定是否遵循了重定向
  • info(): 以email.message_from_string()实例的形式返回页面的元信息
  • getcode(): 返回HTTPResponse 响应的状态码。

2.2 Request 函数实例

实例一:

# 采用 HTTP GET 请求的方法模拟谷歌浏览器访问网站,输出响应上下文
from urllib import request,parse
url = 'http://www.python.org'
headers = {
    
    
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
req = request.Request(url, headers = headers, method = 'GET')
response = request.urlopen(req) 
print(response.read())

实例二:

# 采用 HTTP POST 请求的方法模拟谷歌浏览器访问网站,输出响应上下文
from urllib import request
from urllib import parse
url = 'https://fanyi.baidu.com/sug'
data = {
    
    'py' : 'python'}
data = bytes(parse.urlencode(data), encoding = 'utf-8')
headers = {
    
    
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
req = request.Request(url, data, headers, method = 'POST')
response = request.urlopen(req) 
print(response.read().decode('unicode_escape'))

实例三:

 创建一个 HTTP GET 请求,通过 add_header 添加一个 UserAgent
import urllib.request
import random
url = 'http://www.python.org'
headerUserAgentList = ['Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0']
randomHeaderUserAgent = random.choice(headerUserAgentList) # 随机选取一个 UserAgent
req = urllib.request.Request(url) 
req.add_header('User-Agent', randomHeaderUserAgent) # 添加 UserAgent
response=urllib.request.urlopen(req)
print(req.get_header('User-agent'))
print(req.headers) # 打印请求的 header 信息

2、urllib.error 模块

该urllib.error模块为引发的异常定义异常类urllib.request。基本异常类是URLError。

1.1 urllib.error.URLError异常

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

# 在请求连接时候捕获网址错误引发的异常
from urllib import request, error
try:
    response = request.urlopen('https://www,python,com')
except error.URLError as e:
    print(e.reason)

1.2 urllib.error.HTTPError异常

HTTPError 是 URLError 的子类,专门用来处理 HTTP 请求错误,也可以用作非异常文件状的返回值(与urlopen()返回的东西相同)。主要处理身份验证请求异常的HTTP错误,其包含以下三个属性:

code:返回 HTTP 响应的状态码,如404页面不存在,403禁止访问等。
reason:返回错误的原因。
headers:返回 HTTP 响应头信息。

实例:

# 返回404找不到页面错误
from urllib import request,error
try:  response=request.urlopen('http://python.com/pages/auth/aaa.php')
    print(response.getcode())
except error.HTTPError as e:
    print('1.错误原因:\n%s\n2.状态码:\n%s\n3.响应头信息:\n%s' %(e.reason, e.code, e.headers))
except error.URLError as e:
    print(e.reason)

3、urllib.parse 模块

urllib.parse 模块定义了一个处理 url 的标准接口,用来实现 url 字符串的抽取、合并以及链接转换。(分解组件中的统一资源定位符(URL)字符串(寻址方案,网络位置,路径等),将组件组合回URL字符串,并将“相对URL”转换为给定“基本URL”的绝对URL。)

设计该模块以匹配相对统一资源定位符上的Internet RFC。它支持下列URL方案:file,ftp, gopher,hdl,http,https,imap,mailto,mms, news,nntp,prospero,rsync,rtsp,rtspu,sftp, shttp,sip,sips,snews,svn,svn+ssh,telnet, wais,ws,wss。

该urllib.parse模块定义的功能分为两大类:URL解析URL引用。以下各节将详细介绍这些内容。

1.1 urllib.parse.urlparse()

用于实现 url 字符串的识别和分段,可以分为六个字符串,分别是 scheme (协议),netloc (域名),path (路径),params (参数),query (查询条件)和 fragment (锚点),其结构如下所示:“scheme://netloc/path;parameters?query#fragment”。实际上具体 url 某些字段可能会不存在,比如 “http://www.baidu.com” 只包含了协议和域名。

函数语法:

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

参数说明:

  • urlstring,待解析的 url 字符串。
  • scheme,是默认的协议,比如 http 或者 https,url 字符串中如果不携带相关协议,可以通过 scheme 来指定,如果 url 中指定了相关协议则在 url 中生效。
  • allow_fragments,是否忽略锚点,设置为 False 即 fragment 部分会被忽略,反之不会忽略。

返回类型:
函数返回值是一个命名的tuple获取解析出来的 url 六个字段。
在这里插入图片描述

1.2 urlparse函数实例

from urllib.parse import urlparse
result=urlparse('http://www.baidu.com/index.html;user?id=5#comment')
print(type(result),result,sep='\n')  #返回的是一个元祖
print(result.scheme,result[0])  #可以通过属性或者索引来获取值
print(result.netloc,result[1])
print(result.path,result[2])
print(result.params,result[3])
print(result.query,result[4])
print(result.fragment,result[5])

#返回
#返回结果是一个parseresult类型的对象,它包含6个部分,
#分别是scheme(协议),netloc(域名),path(路径),params(参数),query(查询条件),fragment(锚点)


#结果
<class 'urllib.parse.ParseResult'>
ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
http http
www.baidu.com www.baidu.com
/index.html /index.html
user user
id=5 id=5
comment comment

2.1 urllib.parse.urlparse()

根据返回的元组构造URL urlparse()。与 urlparse 相反,通过列表或者元祖的形式将分段的字符串组合成一个完整的 url 字符串。

函数参数:
urllib.parse.urlparse(parts)

  • parts,可以是列表或者元组。

返回类型:
urlunparse 函数返回一个构造好的 url 字符串。

2.2 urlparse()实例

from urllib.parse import urlunparse
data=['http','www.baidu.com','index.html','user','a=6','comment']
print(urlunparse(data)) #构造一个完整的URL

#输出
http://www.baidu.com/index.html;user?a=6#comment

3.1 urllib.parse.urlsplit()

只返回 url 字符串的5个字段,把 params 合并到 path 中。
函数语法:

 urllib.parse.urlsplit(urlstring, scheme='', allow_fragments=True)

返回类型:
返回值是一个命名元组,它的项可以通过索引或命名属性来访问:
在这里插入图片描述

3.2 urlsplit()实例:

from urllib.parse import urlsplit,urlunsplit
data=['http','www.baidu.com','index.html','n=5','comment']
result=urlunsplit(data)
print(result)

#结果
http://www.baidu.com/index.html?n=5#comment

4.1 urllib.parse.urljoin

该函数用来将基本 url 与另一个 url 组合,更新基本 url 字符串。它会使用 url 对基本 url 中缺失的部分进行补充,比如 scheme (协议)、netloc (域名)和 path (路径)。即根据 url 字符串中带有的字段,对基本 url 中没有的字段进行补充,已存在的字段进行替换。

函数语法:

urllib.parse.urljoin(base,url,allow_fragments = True

urljoin函数参数:

  • base,是一个基本 url。
  • url,将 scheme (协议)、netloc (域名)或 path (路径)字段组合进基本 url 的 url。
  • allow_fragments,是否忽略锚点,设置为 False 即 fragment 部分会被忽略,反之不会忽略

返回值类型:
返回组合成功的 url 字符串。

4.2 urljoin函数实例:

from urllib.parse import urljoin

print(urljoin('http://www.baidu.com','index.html'))
print(urljoin('http://www.baidu.com','http://cdblogs.com/index.html'))
print(urljoin('http://www.baidu.com/home.html','https://cnblog.com/index.html'))
print(urljoin('http://www.baidu.com?id=3','https://cnblog.com/index.html?id=6'))
print(urljoin('http://www.baidu.com','?id=2#comment'))
print(urljoin('www.baidu.com','https://cnblog.com/index.html?id=6'))

#结果
http://www.baidu.com/index.html
http://cdblogs.com/index.html
https://cnblog.com/index.html
https://cnblog.com/index.html?id=6
http://www.baidu.com?id=2#comment
https://cnblog.com/index.html?id=6

该allow_fragments参数具有相同的含义,默认为 urlparse()。
注意 如果url是绝对URL(即以//或开头scheme://),结果中将显示url的主机名和/或方案。可使用和 预处理url,删除可能的方案和netloc部分。urlsplit()urlunsplit()

5.1 urllib.parse.quote()

使用 %xx 转义字符替换字符串中的特殊字符,比如汉字。字母、数字和‘_.-~’字符不会被替换。

函数语法:

urllib.parse.quote(string, safe='/', encoding=None, errors=None)

参数说明:

  • string: 可以是 str 字符串或 bytes 类型。
  • safe: 可选参数,默认是’/’,指明不应该被替换的附加 ASCII 字符。
  • encoding & errors: 可选参数,用来定义如何处理 non-ASCII 字符。一般默认设置编码方法为 encoding=‘utf-8’,errors=‘strict’,这意味着编码错误将引发 UnicodeError。如果 string 是 bytes 类型,不能设置 encoding 和 errors,否则将引发 TypeError。

返回类型:
quote 函数返回一个编码后的字符串。

5.2 quote实例

# 采用 quote 对 url 中的汉字进行编码,输出编码后的结果
import urllib
url = 'http://www.baidu.com/s网络爬虫'
result = urllib.parse.quote(url)
print(result)
url = 'http://www.baidu.com/s?key网络爬虫'
result = urllib.parse.quote(url, '+') # 更改 safe 参数
print(result)

#结果:
https://www.baidu.com/s?key=%E4%B8%AD%E6%96%87

6.1 urllib.parse.unquote()

与 quote 函数相反,把 %xx 转义字符替换成字符。

函数语法:

 urllib.parse.unquote(string, encoding='utf-8', errors='replace')

参数说明:

  • string,必须是 str 字符串。
  • encoding 和 errors,可选参数,定义如何将 %xx 转义字符解码为 Unicode 字符。encoding 默认为 ‘utf-8’,errors 默认为 ‘replace’,表示无效的转义字符将会用占位符替换。

返回类型:
unquote 函数返回一个解码后的字符串。

6.2 unquote实例

# 解码经过 quote 函数处理后的 url,输出解码后的结果。
import urllib
url = 'http://www.baidu.com/网络爬虫'
result = urllib.parse.quote(url)
print(result)
result = urllib.parse.unquote(url)
print(result)

7.1 rllib.parse.urlencode()

urlencode 函数可以将字典转化为 GET 请求中的 query (查询条件),或者将字典转化为 POST 请求中需要上传的数据。

函数语法:

urllib.parse.urlencode(query, doseq=False, safe='', encoding=None, errors=None, quote_via=quote_plus)

参数说明:

  • query: 字典类型。
  • doseq: 允许字典中一个键对应多个值,编码成 query (查询条件)。
  • safe & encoding & errors: 这三个参数由 quote_via 指定。

返回类型:urlencode 函数返回 str 字符串。

7.2 urlencode实例

from urllib.parse import urlencode
params = {
    
    'username':'zs','password':'123'}
base_url='http://www.baidu.com'
url=base_url+'?'+urlencode(params) #将字典转化为get参数
print(url)

#结果t
http://www.baidu.com?password=123&username=zs

8.1 parse_qsl()

将参数转换为元祖组成的列表

from urllib.parse import urlencode,urlsplit,parse_qsl

params = {
    
    'username':'zs','password':'123'}
base_url='http://www.baidu.com'
url=base_url+'?'+urlencode(params) #将字典转化为get参数

query=urlsplit(url).query  #获去URL的query参数条件
print(parse_qsl(query)) #将转换成列表形式的元祖对

#结果
[('username', 'zs'), ('password', '123')]

4、urllib.robotparse 模块

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

语法:

urllib.robotparser.RobotFileParser(url='')

robotparser类常用的方法:

  • set_url():用来设置robots.txt文件的连接,如果在创建RobotFileParser对象是传入了连接,就不需要在使用这个方法设置了
  • read():读取reobts.txt文件并进行分析,它不会返回任何内容,但执行那个了读取和分析操作
  • parse():用来解析robots.txt文件,传入的参数是robots.txt某些行的内容,并安装语法规则来分析内容
  • can_fetch():该方法传入两个参数,第一个是User-agent,第二个是要抓取的URL,返回的内容是该搜索引擎是否可以抓取这个url,结果为True或False
  • mtime():返回上次抓取和分析robots.txt的时间
  • modified():将当前时间设置为上次抓取和分析robots.txt的时间

4.1 robotparse协议:

Robots协议也称为爬虫协议、机器人协议,它的全名叫做网络爬虫排除标准(Robots Exclusion Protocol),用来告诉爬虫和搜索引擎哪些网页可以抓取,哪些不可以抓取,它通常是一个robots.txt的文本文件,一般放在网站的根目录下。
当搜索爬虫访问一个站点时,它首先会检查这个站点根目录下是否存在robots.txt文件,如果存在,搜索爬虫会根据其中定义的爬去范围来爬取,如果没有找到,搜索爬虫会访问所有可直接访问的页面

4.2 robots.txt文件样例:

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

参数说明:

  • User-agent: 爬虫的名称,将其设置为 * 代表协议对任何爬虫有效,如果设置为 Baiduspider 则代表协议仅对百度爬虫有效,要是有多条则对多个爬虫有效,至少需要指定一条。
  • Disallow: 网页中不允许抓取的目录,上述例子中设置的 / 代表不允许抓取所有的页面。
  • Allow: 一般和 Disallow 一起使用,用来排除单独的某些限制,上述例子中设置为 /public/ 表示所有页面不允许抓取,但可以抓取 public 目录。

它实现了对所有搜索爬虫只允许爬取public目录的功能,将上述内容保存为robots.txt文件放在网站根目录下,和网站的入口文件(index.html)放在一起
User-agent描述了搜索爬虫的名称,将其设置为*则代表协议对任何爬虫有效,如设置为Baiduspider则代表规则对百度爬虫有效,如果有多条则对多个爬虫受到限制,但至少需要指定一条

一些常见的搜索爬虫名称:

BaiduSpider  百度爬虫   www.baidu.com
Googlebot  Google爬虫   www.google.com
360Spider  360爬虫   www.so.com
YodaoBot  有道爬虫   www.youdao.com
ia_archiver  Alexa爬虫   www.alexa.cn
Scooter  altavista爬虫     www.altavista.com
Disallow指定了不允许抓取的目录,如上例中设置的/则代表不允许抓取所有的页面
Allow一般和Disallow一起使用,用来排除单独的某些限制,如上例中设置为/public/则表示所有页面不允许抓取,但可以抓取public目录

4.3 robots.tx实例:

#禁止所有爬虫
User-agent: *
Disallow: /

#允许所有爬虫访问任何目录,另外把文件留空也可以
User-agent: *
Disallow:

#禁止所有爬虫访问某那些目录
User-agent: *
Disallow: /home/
Disallow: /tmp/

#只允许某一个爬虫访问
User-agent: BaiduSpider
Disallow:
User-agent: *
Disallow: /

4.4 robotparser实例

from urllib.robotparser import RobotFileParser
rp = RobotFileParser()  #创建对象
rp.set_url('https://www.cnblogs.com/robots.txt') #设置robots.txt连接,也可以在创建对象时指定
rp.read()  #读取和解析文件
print(rp.can_fetch('*','https://i.cnblogs.com/EditPosts.aspx?postid=9170312&update=1')) #坚持链接是否可以被抓取

参考资料:https://docs.python.org/3/library/urllib.html

猜你喜欢

转载自blog.csdn.net/weixin_43853746/article/details/107653579