浅谈urllib和requests

urllibrequests的学习


urllib

urllibpython的基本库之一,内置四大模块,即requesterrorparserobotparser,常用的requesterror,一个用于发送HTTP请求,一个用于处理请求的错误。parse用于对URL的处理,拆分,全并等。

基本用法

# 导入 urllib 中的 request
from urllib import request
# 使用 urlopen,打开一个网址
urllib_response = request.urlopen("http://www.baidu.com")
# read() 方法用于读取响应, decode()  处理,默认 read() 是字节流
print(urllib_response.read().decode("utf-8"))
print(type(urllib_response.read()))  # <class 'bytes'>

问题1:如果在发送请求时断网会怎样
我是在断网的情况下实时的,urllib会提示urllib.error.URLError,即urlopen error [Errno -3] Temporary failure in name resolution,无法解析域名。

from urllib import request, error
# 解决方法是导入 error 模块
# 使用 try except 方法捕获该错误,避免错误影响程序后续运行,也可以将该错误放入日志
try:
    urllib_response = request.urlopen("http://www.baidu.com")
    print(urllib_response.read().decode('utf-8'))
except error.URLError as e:
    print(e)

问题2:如何添加请求头信息

有添加请求头信息的需求,就当然有为什么要添加请求头信息的问题了
要搞明这个问题,就要先了解原生请求头是什么,于是我写一个简单的web server,以下简称server

import socket

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
    server.bind(('127.0.0.1', 5000))
    server.listen(5)
    while True:
        conn, ip = server.accept()
        req = b''
        while True:
            temp = conn.recv(1024)
            req += temp
            if len(temp) < 1024:
                break
        print(req.decode('utf-8'))
        conn.sendall(b'HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n\r\n')
        conn.close()

此时再使用urlopen直接打开127.0.0.1:5000server显示如下信息

GET / HTTP/1.1
Accept-Encoding: identity
Host: 127.0.0.1:5000
User-Agent: Python-urllib/3.7
Connection: close

通过User-Agent可以看出,当前是python-urllib/3.7。即非合法的客户端,如浏览器,目标网站可以通过识别该字段来判断此次访问是否合法,以决定是否禁止其访问。当然,设置了合法的请求头也并非这个爬虫可以安然无恙,目标网站仍然可以通过其他算法也判断这个访问是否合法访问。不过,我们能做的就是把能做的做了

urllib设置请求头
from urllib import request
"""
设置 headers 信息,其为字典格式
使用 request.Request 构造请求
使用 request.urlopen 打开请求
"""
headers = {
    'User-Agent': ('Mozilla/5.0 (X11; Linux x86_64)'
                   ' AppleWebKit/537.36 (KHTML, like Gecko)'
                   ' Chrome/68.0.3440.106 Safari/537.36')
}

req = request.Request(url='http://127.0.0.1:5000', headers=headers)
response = request.urlopen(req)
print(response.read().decode("utf-8"))

server显示如下,User-Agent已被成功修改

GET / HTTP/1.1
Accept-Encoding: identity
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Connection: close

requests

requestspython的第三方库,通过pip install requests即可安装

基本用法

import requests

response = requests.get("http://www.baidu.com")
# 请求百度会出现乱码,因为百度默认解析编码为 utf-8
# requests 的 response 默认为 ISO-8859-1
# 通过 response.encoding 直接设置此次响应解析编码
response.encoding = 'utf-8'
# 通过 response.text 即可查看响应的文本 body
print(response.text)

如果要设置请求头,requests可以直接添加headers参数以设置请求头,而不用像urllibreqeust需要构造一个请求,再进行请求。因为请求头是在其内部已经构建了。

import requests

headers = {
    'User-Agent': ('Mozilla/5.0 (X11; Linux x86_64)'
                   ' AppleWebKit/537.36 (KHTML, like Gecko)'
                   ' Chrome/68.0.3440.106 Safari/537.36')
}
response = requests.get("http://127.0.0.1:5000", headers=headers)
print(response.text)

server的访问请求头信息的前后对比。

GET / HTTP/1.1
Host: 127.0.0.1:5000
User-Agent: python-requests/2.20.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive


GET / HTTP/1.1
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive

参考资料

posted @ 2019-03-01 21:12  朝行  阅读(6802)  评论(0编辑  收藏  举报