python爬虫学习(三):urllib的使用

urllib是python内置的一个可以使用url模块的软件包的集合。

urllib.request 打开和阅读 URLs

urllib.error 包含 urllib.request 抛出的异常

urllib.parse 用于处理 URL

urllib.robotparser 用于解析 robots.txt 文件

1、urllib.request.urlopen()函数用于实现对目标url的访问,是urllib 获取普通网页的基本方法

<code>def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
cafile=None, capath=None, cadefault=False, context=None)/<code>

以上是该方法的一些参数,对源码有兴趣的可以自行跳进去看看。这里做点简单介绍。
参数说明:
url参数:目标资源在网路中的位置。可以是一个表示URL的字符串(如:http://www.baidu.com),也可以是一个urllib.request对象。这里为必传的参数。其余均为可选参数。

data参数:data用来指明发往服务器请求中的额外的参数信息(如:在线翻译,在线答题等提交的内容),data默认是None,此时以GET方式发送请求;当用户给出data参数的时候,改为POST方式发送请求。格式其实就是类似表单的数据格式。

timeout:设置网站的访问超时时间

cafile、capath、cadefault 参数:用于实现可信任的CA证书的HTTP请求。(基本上很少用)

context参数:实现SSL加密传输。(基本上很少用)

那么怎么使用呢,我们这里弄个场景实际运用一下即可。假设访问百度网站,并将返回的内容写到某个html文件里面。在Pycharm里面建一个UrllibDemo1.py文件。

内容如下:

<code>import urllib.request
url = ‘http://www.baidu.com‘
resp = urllib.request.urlopen(url)
print(resp.code) #状态码 如200
print(resp.status) #状态码 如200
print(resp.headers) #头部信息
print(resp.url)
print(resp.info())
print(resp.geturl())
#如果出现乱码,可改成 file.read().decode(‘utf-8’)
data = resp.read()
#使用 with … as … 语句调用,有利于在不适用的时候正常关闭连接
filepath = “/Users/zhouruiyong/Desktop/python/baidu.html” #修改成自己想要存放的文件路径
with open(filepath,”wb”) as fhandle:
fhandle.write(data)/<code>

resp 是 HTTPResponse 对象,是一种类文件对象,除了可以文件的 read() 方法读取它的内容外,还可以通过code,status等获取状态码,headers是返回的头部信息。具体这些信息可自行通过打印信息进行查看。那么如何运行呢,两种方法:

  1. 在命令行中执行:python3 (文件路径/UrllibDemo1.py)
  2. 直接在pycharm里面选中UrllibDemo1.py 文件,右键选择“Run ‘UrllibDemo1’”运行即可。

执行完之后,在对应文件夹下面就会生成一个baidu.html的文件,点击baidu.html既可以看到一个本地的百度的网页,说明已经读取的网页已经成功写入该文件。

2、urllib.request.urlretrieve() 方法能够以另一种形式获取页面内容,它会将页面内容存为临时文件并获取 response 头。

<code> def urlretrieve(url, filename=None, reporthook=None, data=None)/<code>

参数说明:

url:外部或者本地url

filename:指定了保存到本地的路径(如果未指定该参数,urllib会生成一个临时文件来保存数据);

reporthook:是一个回调函数,当连接上服务器、以及相应的数据块传输完毕的时候会触发该回调。我们可以利用这个回调函数来显示当前的下载进度。

data:指post到服务器的数据。

另外该方法返回一个包含两个元素的元组(filename, headers),filename表示保存到本地的路径,header表示服务器的响应头。

<code>import urllib.request
def process(blocknum, blocksize, totalsize): #进度回调方法
‘’’回调函数
@blocknum: 已经下载的数据块
@blocksize: 数据块的大小
@totalsize: 远程文件的大小
‘’’
percent = 100.0*blocknum * blocksize / totalsize
if percent > 100:
percent = 100
print(“%.2f%%” % percent)

url = ‘http://www.sohu.com‘ #网页地址
fileName = ‘/Users/zhouruiyong/Desktop/python/sina.html’ #保存的本地文件地址
fileName,headers = urllib.request.urlretrieve(url,fileName,process)
print(fileName)
print(headers)/<code>

注:有时候回出现totalsize为-1的情况,不是你代码的问题,而是有些地址不支持返回Content-Length的信息,比如范围百度http://www.baidu.com, 你会发现totalsize一直都是-1。urlretrieve在执行过程中会产生一些缓存,如果想清除这些缓存信息,可以用urllib.request.urlcleanup() 进行清除。如果需要对网址进行编码和解码可以使用如下代码

编码:

<code>>>> urllib.request.quote(“http://www.sina.com.cn“)

‘http%3A//www.sina.com.cn’/<code>

解码:

<code>>>> urllib.request.unquote(‘http%3A//www.sina.com.cn’)

‘http://www.sina.com.cn‘/<code>

3.有时候我们无法简单通过上面的方法简单用网址爬取一些网页,这是因为有些网页为了防止别人采集其信息进行了一些反爬虫的设置。这时候,就要设置一些Headers的信息,模拟浏览器去访问这些网站。


python爬虫学习(三):urllib的使用


如果还不清楚什么是header的同学,可以打开谷歌浏览器,右键选择检查,然后在弹出的框里面选择network,这是随便访问一个网址,选择Headers即可查看相应的请求头信息。

接下来我们使用两种爬虫模拟成流浪器访问网页.这里特别注意上图里面的User Agent。User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等

使用build_opener()修改报头

<code>import urllib.request
url = ‘http://www.sohu.com‘ #网页地址
headers = (“User-Agent”,
“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) “
“AppleWebKit/537.36 (KHTML, like Gecko)”
“ Chrome/73.0.3683.103 Safari/537.36”)
opener = urllib.request.build_opener();
opener.addheaders = [headers]
data = opener.open(url).read();
print(data)/<code>

使用add_header()添加报头

这里使用的是urllib.request.Request()下的add_header实现浏览器的模拟

<code>import urllib.request 

url = ‘http://www.sohu.com‘ #网页地址
req = urllib.request.Request(url)
req.add_header(“User-Agent”,
“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) “
“AppleWebKit/537.36 (KHTML, like Gecko)”
“ Chrome/73.0.3683.103 Safari/537.36”)
data = urllib.request.urlopen(req).read()
print(data)/<code>

4.超时设置

简单来说,就是设置某个时间,超过这个时间,如果还没有返回数据就当作请求失败。对python来说会抛出异常。我们可以这样来请求

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

即设置超时时间为1秒。可以放在try..except里面。

5.get和post请求

这里使用urllib.parse.urlencode()进行编码。

get请求:

<code>#构造一个字典参数
base_url = “网址”
data_dict={
“username”:”123456”,
“password”:”123456”
}
data_string=urllib.parse.urlencode(data_dict)
new_url=base_url+”?”+data_string
response=urllib.request.urlopen(new_url)print(response.read().decode(‘utf-8’))/<code>

注:如果url网址中含有中文,需要用上面提到的用urllib.request.quote进行编码

post请求:

<code>#定义一个字典参数
data_dict={“username”:”123456”,”password”:”123456”}
#使用urlencode将字典参数序列化成字符串
data_string=urllib.parse.urlencode(data_dict)
#将序列化后的字符串转换成二进制数据,因为post请求携带的是二进制参数
last_data=bytes(data_string,encoding=’utf-8’)
#如果给urlopen这个函数传递了data这个参数,那么它的请求方式则不是get请求,而是post请求
response=urllib.request.urlopen(“网址”,data=last_data)
print(response.read().decode(‘utf-8’))/<code>


分享到:


相關文章: