python爬虫之urllib库(一)

  urllib库

  urllib库是python提供的一种用于操作URL的模块,python2中是urllib和urllib2两个库文件,python3中整合在了urllib一个库中。即在Python中导入和调用方法也发生了改变。

python2和python3中urllib库变化对比
python2 python3
import urllib2 import urllib.request,urllib.request
import urllib import urllib.reqest,urllib.error,urllib.parse
import parse import urllib.parse
urllib2.urlopen urllib.request.urlopen
urllib.urlencode urllib.parse.urlencode
urllib.quote urllib.request.quote
cookielib.CookieJar http.CookieJar
urllib2.Request urllib.request.Request

  使用urllib库快速爬取网页

  使用urllib库需要导入urllib库中对应的模块。

  1.   import urllib.request

  导入对应模块以后,使用模块中的urlopen()方法打开并爬取网页。例如,爬取百度首页(http://www.baidu.com),并保存在变量file中。

  1.   file = urllib.request.urlopen(‘http://www.baidu.com’)

  使用print(file)查看一下变量file中保存的内容,查看结果为:<http.client.HTTPResponse object at 0x0000000002DCBB38>。由此看出,urlopen()方法爬取网页返回的结果是一个HTTP响应对象,读取对象中的内容需要其他方式。

  读取内容的三种方式及其用法:

  1. file.read()读取文件的全部内容,read()方法读取的内容赋值给一个字符串变量。
  2. file.readlines()读取文件的全部内容,readlines()方法读取的内容赋值给一个列表变量。
  3. file.readline()读取文件的一行内容。
  1. data = file.read() # 所有内容赋值给字符串
  2. print(data)
  3. data_lines = file.readlines() # 所有内容赋值给列表
  4. print(data_lines)
  5. data_line = file.readline() # 单行内容
  6. print(data_line)
  7. data_line_next = file.readline()
  8. print(data_line_next) # 读取下一行

  成功爬取了一个网页以后,将网页保存在本地需要使用文件读写操作。文件读写的具有两种写法:

  法一:

  1. fhandle = open('D:/Spider/test/baidu.html', 'wb')
  2. fhandle.write(data)
  3. fhandle.close()

  法二:

  1.   with open('D:/Spider/test/baidu.html', 'wb') as fhandle:
  2.   fhandle.write(data)

  两种写法都是先使用open()方法按照文件目录D:/Spider/test/ 找到并打开名为baidu.html的文件,文件操作模式为'wb',表示bytes类型数据写模式,然后使用write()方法写入。区别在于with方法在数据写入以后会自动关闭文件,而法一需要调用close()方法关闭文件。

  注意一个问题:urlopen()返回的HTTP响应对象通过head()读取以后,可以看到b‘  ’形式的字符串,此类型数据为bytes类型,对应文件写入的中'wb',‘rb’等。我们知道python中,bytes类型数据是适合用于数据的传输和存储,而如果bytes类型数据需要处理,则需要转化为str类型数据。

  str类型与bytes类型之间的数据转换方式:

  1. str类型数据转化为bytes类型数据:编码,str.encode('utf-8'),其中utf-8为统一码,是一种编码格式。
  2. bytes类型数据转化为str类型数据:解码,bytes.decode('utf-8')。
  1. import urllib.request
  2.  
  3. file = urllib.request.urlopen('http://www.baidu.com')
  4. data = file.read().decode() # decode()转bytes为str
  5.  
  6. with open('D:/Spider/test/baidu.html', 'w') as fhandle: # 以str类型写入文件
  7. fhandle.write(data)

  按照文件目录找到baidu.html文件,使用浏览器打开,可以看到本地版百度首页。只是图片暂时没有爬取过来。

  此外,可以使用getcode()方法查看爬取网页时的状态码,geturl()方法获取当时爬取的url地址。

  1. import urllib.request
  2.  
  3. file = urllib.request.urlopen('http://www.baidu.com')
  4. code = file.getcode()
  5. url = file.geturl()
  6. print(code)
  7. print(url)

  除了上面使用的方法,还可以使用urllib.request中urlretrieve()方法直接将对应信息写入本地文件,格式:urllib.request.urlretrieve(url, filename = '本地文件地址')。

  1. import urllib.request
  2.  
  3. url = 'http://www.baidu.com'
  4. filename = urllib.request.urlretrieve(url, filename='D:/Spider/test/baidu-2.html')

  按照文件目录找到baidu-2.html文件,使用浏览器打开,可以看到本地版百度首页。此外,使用print(filename)查看,得出('D:/Spider/test/baidu-2.html', <http.client.HTTPMessage object at 0x0000000002DEC2E8>),filename是以元组形式存储了本地文件地址和HTTP响应消息对象。

  使用urllib.request.retrieve()方法爬取网页本地化保存会产生一些缓存,可以使用urlcleanup()方法清除缓存。

  1.   urllib.request.urlcleanup()

  URL编码:一般来说,URL标准只允许一部分ASCII字符在url中使用,像汉字、“:”、“&”等字符是不符合URL标准的,需要进行URL编码。根据传参形式不同,URL编码又分为两种方式。

  方式一:使用urllib.request.quote()对单一参数进行编码。

  1. url = 'http://www.baidu.com/s?wd='
  2. search = '编程' # 单一参数
  3. search_url = url + urllib.request.quote(search) # 参数编码,合并url
  4. print(search_url)

  方式二:使用urllib.parse.urlencode()对多个参数以字典形式传入进行编码。

  1. import urllib.parse
  2.  
  3. url = 'http://www.baidu.com/s?'
  4. params = {
  5. 'wd': '中文',
  6. 'key': '张',
  7. 'value': '三'
  8. }
  9.  
  10. str_params = urllib.parse.urlencode(params) # 字典传参拼接方式,urlencode()和quote()相似,urlencode对多个参数转义
  11. print(str_params) # wd=%E4%B8%AD%E6%96%87&key=%25E5%25BC%25A0&value=%E4%B8%89
  12. search_url = url + str_params
  13. print(search_url)

  使用headers属性模拟浏览器

  有时,使用爬虫爬取一些网页的时候,会返回403错误,即禁止访问的错误。是因为网页为了防止恶意采集信息的行为设置了一些反爬措施。对于这部分网页,我们可以尝试设置一些headers信息,模拟成浏览器去访问这些网页。由于urlopen()不支持一些HTTP的高级特性,要添加可以使用opener对象或者Request类来进行。

  三种添加headers信息的方式,参阅python爬虫之User-Agent用户信息

  方法一:使用build_opener()修改报头

  1. import urllib.request
  2.  
  3. url= "http://blog.csdn.net/weiwei_pig/article/details/51178226"
  4. headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0")
  5.  
  6. opener = urllib.request.build_opener()
  7. opener.addheaders = [headers]
  8. data=opener.open(url).read()

  通过build_opener()方法创建opener对象,而opener对象是由OpenerDirector类实例化来的。

  OpenerDirector类的实例属性self.addheaders默认初始值为[('User-agent', client_version)](列表元素为元组型嵌套),外部调用赋值修改opener.addheaders属性。

  后调用OpenerDirector类的实例方法open()发送HTTP请求。

  方法二:使用Request类实例化静态添加报头

  1. import urllib.request
  2.  
  3. url= "http://www.baidu.com"
  4. headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0")
  5.  
  6. req=urllib.request.Request(url, headers= headers)
  7. data=urllib.request.urlopen(req).read()

  方法三:使用Request类的实例方法add_headers()动态添加报头(注意源码中add_headers()方法的首字母大写的key才可以取value)

  1. import urllib.request
  2.  
  3. url= "http://www.baidu.com"
  4.  
  5. req=urllib.request.Request(url)
  6. req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0')
  7. data=urllib.request.urlopen(req).read()

  方法二和方法三都是对Request类的操作,方法二是通过对类的初始化添加headers,方法三是调用类中的实例方法add_header()添加headers,Request类源码:

  1. class Request:
  2.  
  3. def __init__(self, url, data=None, headers={},
  4. origin_req_host=None, unverifiable=False,
  5. method=None):
  6. self.full_url = url
  7. self.headers = {}
  8. self.unredirected_hdrs = {}
  9. self._data = None
  10. self.data = data
  11. self._tunnel_host = None
  12. for key, value in headers.items():
  13. self.add_header(key, value)
  14. if origin_req_host is None:
  15. origin_req_host = request_host(self)
  16. self.origin_req_host = origin_req_host
  17. self.unverifiable = unverifiable
  18. if method:
  19. self.method = method
  20.  
  21. @property
  22. def full_url(self):
  23. if self.fragment:
  24. return '{}#{}'.format(self._full_url, self.fragment)
  25. return self._full_url
  26.  
  27. @full_url.setter
  28. def full_url(self, url):
  29. # unwrap('<URL:type://host/path>') --> 'type://host/path'
  30. self._full_url = unwrap(url)
  31. self._full_url, self.fragment = splittag(self._full_url)
  32. self._parse()
  33.  
  34. @full_url.deleter
  35. def full_url(self):
  36. self._full_url = None
  37. self.fragment = None
  38. self.selector = ''
  39.  
  40. @property
  41. def data(self):
  42. return self._data
  43.  
  44. @data.setter
  45. def data(self, data):
  46. if data != self._data:
  47. self._data = data
  48. # issue 16464
  49. # if we change data we need to remove content-length header
  50. # (cause it's most probably calculated for previous value)
  51. if self.has_header("Content-length"):
  52. self.remove_header("Content-length")
  53.  
  54. @data.deleter
  55. def data(self):
  56. self.data = None
  57.  
  58. def _parse(self):
  59. self.type, rest = splittype(self._full_url)
  60. if self.type is None:
  61. raise ValueError("unknown url type: %r" % self.full_url)
  62. self.host, self.selector = splithost(rest)
  63. if self.host:
  64. self.host = unquote(self.host)
  65.  
  66. def get_method(self):
  67. """Return a string indicating the HTTP request method."""
  68. default_method = "POST" if self.data is not None else "GET"
  69. return getattr(self, 'method', default_method)
  70.  
  71. def get_full_url(self):
  72. return self.full_url
  73.  
  74. def set_proxy(self, host, type):
  75. if self.type == 'https' and not self._tunnel_host:
  76. self._tunnel_host = self.host
  77. else:
  78. self.type= type
  79. self.selector = self.full_url
  80. self.host = host
  81.  
  82. def has_proxy(self):
  83. return self.selector == self.full_url
  84.  
  85. def add_header(self, key, val):
  86. # useful for something like authentication
  87. self.headers[key.capitalize()] = val
  88.  
  89. def add_unredirected_header(self, key, val):
  90. # will not be added to a redirected request
  91. self.unredirected_hdrs[key.capitalize()] = val
  92.  
  93. def has_header(self, header_name):
  94. return (header_name in self.headers or
  95. header_name in self.unredirected_hdrs)
  96.  
  97. def get_header(self, header_name, default=None):
  98. return self.headers.get(
  99. header_name,
  100. self.unredirected_hdrs.get(header_name, default))
  101.  
  102. def remove_header(self, header_name):
  103. self.headers.pop(header_name, None)
  104. self.unredirected_hdrs.pop(header_name, None)
  105.  
  106. def header_items(self):
  107. hdrs = self.unredirected_hdrs.copy()
  108. hdrs.update(self.headers)
  109. return list(hdrs.items())

  考虑:实例属性self.headers初始值为空字典{},能否像方法一,在外部调用时赋值修改实例属性。

  1. import urllib.request
  2.  
  3. url = "http://www.baidu.com"
  4. headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0"}
  5.  
  6. req = urllib.request.Request(url)
  7. req.headers = headers
  8. data = urllib.request.urlopen(req).read()
  9.  
  10. with open('t.html', 'wb') as fhandle:
  11. fhandle.write(data)

  测试验证方法,找到t.html文件使用浏览器打开,按F12切换到DevTools-Network选项,刷新页面,出现

  点击黑色箭头所指列表项的任意一下,右侧出现

  下拉找到Request Headers,展开找到User-Agent项,对照上述代码User-Agent信息验证可以使用外部调用实例属性修改。

  上述过程反过来,则为手动抓包,获取User-Agent信息了。

  

  

python爬虫之urllib库(一)的更多相关文章

  1. python爬虫之urllib库(三)

    python爬虫之urllib库(三) urllib库 访问网页都是通过HTTP协议进行的,而HTTP协议是一种无状态的协议,即记不住来者何人.举个栗子,天猫上买东西,需要先登录天猫账号进入主页,再去 ...

  2. python爬虫之urllib库(二)

    python爬虫之urllib库(二) urllib库 超时设置 网页长时间无法响应的,系统会判断网页超时,无法打开网页.对于爬虫而言,我们作为网页的访问者,不能一直等着服务器给我们返回错误信息,耗费 ...

  3. python爬虫之urllib库介绍

    一.urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求.其常被用到的子模块在Python3中的为urllib.request和urllib. ...

  4. python 爬虫之 urllib库

    文章更新于:2020-03-02 注:代码来自老师授课用样例. 一.初识 urllib 库 在 python2.x 版本,urllib 与urllib2 是两个库,在 python3.x 版本,二者合 ...

  5. Python 爬虫之urllib库的使用

    urllib库 urllib库是Python中一个最基本的网络请求库.可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据. urlopen函数: 在Python3的urlli ...

  6. python爬虫入门urllib库的使用

    urllib库的使用,非常简单. import urllib2 response = urllib2.urlopen("http://www.baidu.com") print r ...

  7. python爬虫之urllib库

    请求库 urllib urllib主要分为几个部分 urllib.request 发送请求urllib.error 处理请求过程中出现的异常urllib.parse 处理urlurllib.robot ...

  8. Python爬虫系列-Urllib库详解

    Urllib库详解 Python内置的Http请求库: * urllib.request 请求模块 * urllib.error 异常处理模块 * urllib.parse url解析模块 * url ...

  9. python爬虫03 Urllib库

    Urllib   这可是 python 内置的库 在 Python 这个内置的 Urllib 库中 有这么 4 个模块 request request模块是我们用的比较多的 就是用它来发起请求 所以我 ...

随机推荐

  1. 使用第三方库连接MySql数据库:PyMysql库和Pandas库

    使用PyMysql库和Pandas库链接Mysql 1 系统环境 系统版本:Win10 64位 Mysql版本: 8.0.15 MySQL Community Server - GPL pymysql ...

  2. TIMER_PWM_CAPTURE

  3. ORACLE B-TREE(B树)索引

    内容简介: 1.普通B-TREE 索引; 2.唯一B-TREE 索引; 3.复合索引; ORACLE 默认的索引类型为B-TREE 索引,表中的行标识符(ROWID)和行相关的列值被存储在一个平衡树的 ...

  4. 实践作业4:Web测试实践(小组作业)每日任务记录2

    实践作业4:Web测试实践(小组作业)每日任务记录2 会议时间:2017年12月22日 会议地点:东九教学楼自习区 主  持  人:王晨懿 参会人员:王晨懿.余晨晨.郑锦波.杨潇.侯欢.汪元 记  录 ...

  5. LinqPad介绍,下载,用法说明

    介绍一款用于Linq运算和测试的工具,LinqPad.我感觉这个工具非常优秀,不只是功能上优秀,在使用上也非常优秀,让我爱不释手. LinqPad官方地址:http://www.linqpad.net ...

  6. oracle中的表空间(tablespace)、方案(schema)、段(segment)、区(extent)、块(block)

    数据文件和日志文件是数据库中最重要的文件.它们是数据存储的地方.每个数据库至少有一个与之相关的数据文件,通常情况下不只一个,有很多.数据在数据文件中是如何组织的?要了解这些内容我们首先必须理解什么是表 ...

  7. 两个SSH2间免密码登录

    SSH2免密码登录OpenSSHhttp://blog.csdn.net/aquester/article/details/23836299 OpenSSH免密码登录SSH2http://blog.c ...

  8. WCF服务编程 读书笔记——第1章 WCF基础(2)

    续:第1章 WCF基础(1) 元数据交换 服务有两种方案可以发布自己的元数据.一种是基于HTTP-GET协议提供元数据, 另一种则是后面将要讨论的使用专门的终结点的方式.WCF能够为服务自动提供基于H ...

  9. mybatis 单表的增删改查

    添加数据返回id mapper.xml mapper -> insert -> selectKey mybatis 内置别名

  10. java 调用javascript

    首先我们在D盘的根目录下有一个js文件 名叫 common.js 假设里面有一个这样的方法 /** * @param int *            _number 你想要的最大值 * @param ...