urllib模块提供的上层接口使用户能够像读取本地文件一样读取WWW或FTP上的数据,使用起来比C++、C#等编程语言更加方便。
常用的方法如下:
1、urlopen
urlopen(url , data = None ,proxies = Nonne)
该方法用于创建一个远程URL的类文件对象,然后像本地文件一样操作这个类文件对象来获取远程数据。参数url表示远程数据的路径,一般是网址;参数data表示post方式提交到url的数据;参数proxies用于设置代理;返回值是一个类文件对象。
urlopen常用方法:
方法 | 用途 |
read(), readlines() , close() | 这些方法的使用方式与文件对象完全一样,包括文件的读取和文件的关闭操作 |
info() | 返回一个httplib,HTTPMessage对象;表示远程服务器返回的头信息 |
geturl() | 返回请求的URL |
getcode() | 返回HTTP状态码。如果是 HTTP 请求,则返回200表示请求成功完成,404表示网址未找到 |
下面看一下代码:
import urllib.request
import webbrowser as web
url = "http://www.baidu.com"
content = urllib.request.urlopen(url)
print(content.info()) #头信息
print(content.geturl()) #请求url
print(content.getcode()) #HTTP状态字
#保存网页至本地浏览器打开
open("baidu.html","wb+").write(content.read())
web.open_new_tab("baidu.html")
由于我使用的是Python3.7.0所以代码会和老师书上写的有一些不同,老师使用的是Python2.6版本如果按照老师的写会有以下两个错误:
Traceback (most recent call last):
File "D:\Python\first reptile\first reptile.py", line 4, in <module>
content = urllib.urlopen(url)
AttributeError: module 'urllib' has no attribute 'urlopen'
>>>
这个错误解决的办法是将语句:
import urllib
import webbrowser as web
url = "http://www.baidu.com"
content = urllib.urlopen(url)
改为 :
import urllib.request
import webbrowser as web
url = "http://www.baidu.com"
content = urllib.request.urlopen(url)
第二个错误是:
Traceback (most recent call last):
File "D:\Python\first reptile\first reptile.py", line 12, in <module>
open("baidu.html","w").write(content.read())
TypeError: write() argument must be str, not bytes
>>>
错误产生的原因是因为存储方式默认是二进制,将代码:
open("baidu.html","w").write(content.read())
改为:
open("baidu.html","wb+").write(content.read())
整段代码的运行结果:
Bdpagetype: 1
Bdqid: 0xc80a20df00045830
Cache-Control: private
Content-Type: text/html
Cxy_all: baidu+806ada47b0e62b5e79c07a42e495ba04
Date: Sat, 02 Feb 2019 02:44:46 GMT
Expires: Sat, 02 Feb 2019 02:44:43 GMT
P3p: CP=" OTI DSP COR IVA OUR IND COM "
Server: BWS/1.1
Set-Cookie: BAIDUID=6AE9E5C3D0C9D4508063A0C60B4B0275:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BIDUPSID=6AE9E5C3D0C9D4508063A0C60B4B0275; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1549075486; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: delPer=0; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1431_21105_28329_26350_22158; path=/; domain=.baidu.com
Vary: Accept-Encoding
X-Ua-Compatible: IE=Edge,chrome=1
Connection: close
Transfer-Encoding: chunked
http://www.baidu.com
200
>>>
代码说明 :调用urllib.request.urlopen(url)函数打开百度链接,并输出头信息、url、HTTP状态码等信息
代码import webbrowser as web引用webbrowser第三方库,因此可以使用类似 module_name.method调用对应的函数。
open("baidu.html","wb+").write(content.read())表示在本地创建静态的baidu.html文件,并读取打开的百度网页内容,执行文件写操作。
web.open_new_tab("baidu.html")表示通过浏览器打开已经下载的静态网页新标签。当然也可以使用web.open_new_tab("http://www.baidu.com")在浏览器中直接打开在线网页。
2、urlretrieve
urlretrieve方法是将远程数据下载到本地
urlretrieve(url , filename = None , reporthook = None , data = None)
参数filename指定了保存到本地的路径,如果省略该参数 ,则urllib会自动生成一个临时文件来保存数据;参数reporthook是一个回调函数,当连接上服务器,相应的数据块传输完毕时,会触发该回调函数,通常使用该回调函数来显示当前的下载进度;参数data是指传递到服务器的数据。
下面通过例子来演示如何将新浪首页爬取到本地,并保存在“D:/xinlang.html”文件中,同时显示下载进度:
import urllib.request
#函数功能:下载文件至本地,并显示下载进度
#a-已经下载的数据块,b-数据块的大小,c-远程文件的大小
def Download(a,b,c):
per = 100.0 *a*b/c
if per > 100:
per = 100
print('%.2f' % per)
url = 'http://www.sina.com.cn'
local = 'D://xinlang.html'
urllib.request.urlretrieve(url , local ,Download)
运行结果:
-0.00
-819200.00
-1638400.00
-2457600.00
-3276800.00
-4096000.00
-4915200.00
-5734400.00
-6553600.00
-7372800.00
-8192000.00
-9011200.00
-9830400.00
-10649600.00
-11468800.00
-12288000.00
-13107200.00
-13926400.00
-14745600.00
-15564800.00
-16384000.00
-17203200.00
-18022400.00
-18841600.00
-19660800.00
-20480000.00
-21299200.00
-22118400.00
-22937600.00
-23756800.00
-24576000.00
-25395200.00
-26214400.00
-27033600.00
-27852800.00
-28672000.00
-29491200.00
-30310400.00
-31129600.00
Traceback (most recent call last):
File "D:\Python\first reptile\first reptile.py", line 11, in <module>
urllib.request.urlretrieve(url , local ,Download)
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 276, in urlretrieve
block = fp.read(bs)
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 447, in read
n = self.readinto(b)
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 481, in readinto
return self._readinto_chunked(b)
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 576, in _readinto_chunked
chunk_left = self._get_chunk_left()
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 544, in _get_chunk_left
chunk_left = self._read_next_chunk_size()
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 504, in _read_next_chunk_size
line = self.fp.readline(_MAXLINE + 1)
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\socket.py", line 589, in readinto
return self._sock.recv_into(b)
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 1049, in recv_into
return self.read(nbytes, buffer)
File "C:\Users\xiaoyi\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 908, in read
return self._sslobj.read(len, buffer)
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
>>>