urllib 是 Python 内置的 HTTP 请求库,它包含四个模块:
1.发送请求
2.处理异常模块
3.parse解析模块的使用
4.Handler处理器 和 自定义Opener
5.robot协议介绍
1)发送请求之get方法
GET请求一般用于我们向服务器获取数据
爬取网页:
导入模块:
import urllib.request
import re
class NeiHan():
def __init__(self):
#定位爬的url地址
self.url = 'http://www.neihan8.com/wenzi//'
#请求头
self.headers = {
'User-Agent': "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0"
}
def loadpage(self, url):
# 构建request
request = urllib.request.Request(url=self.url, headers=self.headers)
# 发起请求
response = urllib.request.urlopen(request)
# 内容编码
content = response.read().decode()
#正则:
pattern = re.compile(r'<div.*?class="desc">(.*?)</div>', re.S)
#提取内容
neihan_list = pattern.findall(content)
#内容写入
for neihan in neihan_list:
self.writepage(neihan)
#写入到neihan.txt文件
def writepage(self, neihan):
with open('neihan.txt', 'a') as f:
f.write(neihan + '\n')
if __name__ == '__main__':
c = NerHan()
c.loadpage()
2)发送请求之post方法
Request请求对象的里有data参数,它就是用在POST里的,我们要传送的数据就是这个参数data,data是一个字典,里面要匹配键值对。
import urllib.request
#工具
import urllib.parse
#请求头
headers = {
'User-Agent': 'Mozilla / 5.0(X11;Ubuntu;Linuxx86_64;rv: 54.0) Gecko / 20100101Firefox / 54.0'
}
#测试
url = 'https://httpbin.org/post'
#构建post请求的表单数据
data = {
'name': 'xiaohu',
'age': 20
}
#将参数转为url编码格式,并转为bytes类型的数据
params = urllib.parse.urlencode(data).encode()
#构建request
request = urllib.request.Request(url=url, data=params, headers=headers)
#发起请求获取响应结果
response = urllib.request.urlopen(request)
content = response.read().decode()
print(content)
GET方式是直接以链接形式访问,链接中包含了所有的参数,服务器端用Request.QueryString获取变量的值。如果包含了密码的话是一种不安全的选择,不过你可以直观地看到自己提交了什么内容。
POST则不会在网址上显示所有的参数,服务器端用Request.Form获取提交的数据,在Form提交的时候。但是HTML代码里如果不指定 method 属性,则默认为GET请求,Form中提交的数据将会附加在url之后,以?分开与url分开。
url.parse :定义了url的标准接口,实现url的各种抽取
parse模块的使用:url的解析,合并,编码,解码
import urllib.parse
url = 'https://book.qidian.com/info/1004608738?wd=123&page=20#Catalog'
# 把URL拆开
print(urllib.parse.urlparse(url))
url_parmas = ('https', 'book.qidian.com', '/info/1004608738', '', 'wd=123&page=20', 'Catalog')
print(urllib.parse.urlunparse(url_parmas))
#将某一个不完整的链接拼接为一个完整链接
base_url = 'https://book.qidian.com/info/1004608738?wd=123&page=20#Catalog'
sub_url = '/info/100861102'
print(urllib.parse.urljoin(base_url,sub_url))
#将字典形式的参数序列化为url编码后的字符串
#urllib.parse.urlencode()
parmas_str = 'page=20&wd=123'
parmas = urllib.parse.parse_qs(parmas_str)
print(parmas)
#将中文转换为URL编码格式
word = '中国梦'
url = 'http://www.baidu.com/s?wd='+urllib.parse.quote(word)
print(urllib.parse.quote(word))
print(url)
#将URL编码进行解码
url = 'http://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%E6%A2%A6'
print(urllib.parse.unquote(url))
urllib 的异常错误处理
我们在发送请求的过程中,如果网络环境不好,或者出现了其他问题,会出现请求异常,如果不处理这些异常,程序很可能会崩溃,所以我们需要处理请求异常问题.
这里主要说的是URLError和HTTPError,以及对它们的错误处理。
URLError:来自urllib库的error模块,继承自OSError,由request模块产生的异常都可以通过捕捉这个类来处理.
产生的原因主要有:
- 没有网络连接
2.服务器连接失败 - 找不到指定的服务器
它具有一个属性reason,返回错误的原因
import urllib.error
import urllib.request
try:
urllib.request.urlopen('http://www.baidu.com',timeout=0.01)
except urllib.error.URLError as e:
print(e.reason)
try:
urllib.request.urlopen('https://www.qidian.com/all/nsacnscn.htm')
except urllib.error.HTTPError as e:
print(e.reason)
print(e.code)
print(e.headers)
try:
urllib.request.urlopen('https://www.qidian.com/all/nsacnscn.htm')
except Exception as e:
print(e)
常见的HTTP状态码:
200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
302 - 资源(网页等)被临时转移到其它URL
401 - 未授权
403 - 禁止访问
408 - 请求超时
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误
503 - 服务器不可用
基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高级功能。所以要支持这些功能:
使用相关的 Handler处理器 来创建特定功能的处理器对象;
然后通过 urllib.request.build_opener()方法使用这些处理器对象,创建自定义opener对象;
使用自定义的opener对象,调用open()方法发送请求。
import urllib.request
url = "http://www.baidu.com"
# 处理http请求 ctrl+shift+u 大写变小写
httphandler = urllib.request.HTTPHandler(debuglevel=1)
# 处理https请求的handler
# httpshandler = urllib.request.HTTPsHandler()
# 第二步 创建一个opener
opener = urllib.request.build_opener(httphandler)
# 创建一个请求
request = urllib.request.Request(url=url)
# 发送请求
# urllib.request.urlopen(request)这是原来的发送请求方法
response = opener.open(request)
# 读取数据
content = response.read().decode()
with open('baidu.html', 'w') as f:
f.write(content)
代理:
基本原理: 代理实际上指的就是代理服务器,英文叫作proxy server,它的功能是代理网络用户去取得网络信息。形象地说,它是网络信息的中转站。在我们正常请求一个网站时,其实是发送了请求给Web服务器,Web服务器把响应传回给我们。如果设置了代理服务器,实际上就是在本机和服务器之间搭建了一个桥,此时本机不是直接向Web服务器发起请求,而是向代理服务器发出请求,请求会发送给代理服务器,然后由代理服务器再发送给Web服务器,接着由代理服务器再把Web服务器返回的响应转发给本机。这样我们同样可以正常访问网页,但这个过程中Web服务器识别出的真实IP就不再是我们本机的IP了,就成功实现了IP伪装,这就是代理的基本原理
代理的作用:
1.突破自身IP访问限制
2.访问一些单位或团体内部资源
3.提高访问速度
4.隐藏真实IP
1.根据协议划分:
FTP代理服务器
HTTP代理服务器
SSL/TLS代理
SOCKS代理
根据匿名内容划分:
高度匿名代理
普通匿名代理
透明代理
import urllib.request
import urllib.parse
# 免费代理
# proxy = {
# 'http': '61.176.223.7:58822',
# 'https': '218.76.253.201:61408',
# }
# 构建一个私密代理Handler,需要加上私密代理账户的用户名和密码
authproxy = {
"https": "496155678:tx4p1gbw@112.74.108.33:16817",
# "http": "496155678:tx4p1gbw@112.74.108.33:16817"
}
# 创建处理代理的handler
proxyhandler = urllib.request.ProxyHandler(
proxies = authproxy
)
# 创建一个opener
opener = urllib.request.build_opener(proxyhandler)
# 构造一个请求
# request = urllib.request.Request(url='http://www.baidu.com')
# 发送请求
# response = opener.open(request)
url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0',
'Referer': 'https://www.lagou.com/jobs/list_java?labelWords=&fromSearch=true&suginput=?labelWords=hot',
'X-Requested-With': 'XMLHttpRequest',
'Origin': 'https://www.lagou.com',
'Cookie': '_ga=GA1.2.454842362.1523882199; user_trace_token=20180416203639-cf8fa21d-4172-11e8-87b1-525400f775ce; LGUID=20180416203639-cf8fa4c6-4172-11e8-87b1-525400f775ce; _gid=GA1.2.357008350.1545287354; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22166af40632b7e4-0d1fb84d73b02a-346e780b-1024000-166af40632c733%22%2C%22%24device_id%22%3A%22166af40632b7e4-0d1fb84d73b02a-346e780b-1024000-166af40632c733%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=66; index_location_city=%E5%85%A8%E5%9B%BD; JSESSIONID=ABAAABAAAFCAAEG69A81B4AAC041DE1DF146C1C4175134C; _gat=1; LGSID=20181221104450-63482a8c-04ca-11e9-9f54-5254005c3644; PRE_UTM=; PRE_HOST=www.baidu.com; PRE_SITE=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3D_T_xi2Zd5W1_6G3zKFKezYvVu0lSBC5FQIr4HeQYOEa%26wd%3D%26eqid%3Dbdffabc60000f773000000025c1c5397; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1545303897,1545303905,1545352391,1545360291; LG_LOGIN_USER_ID=2d426d30feeb0777f3fc1657c0ea320fe465c87ef5bbbe5e; _putrc=42E0B5E87AD73B68; login=true; unick=%E8%B5%B5%E5%BA%86%E5%85%83; SEARCH_ID=94e60c5736f746ca915c2fad34993630; LGRID=20181221105414-b345f6f4-04cb-11e9-87ca-525400f775ce; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1545360856; TG-TRACK-CODE=index_hotsearch; gate_login_token=275f6c1c24a8e56f015e157826f0c802878a39df65bfedc1',
}
data = {
'first': 'false',
'pn': 2,
'kd': 'java'
}
# 传递的数据要进行二进制编码
params = urllib.parse.urlencode(data).encode()
request = urllib.request.Request(url=url, headers=headers, data=params)
#把自定义的opener当初全局使用
# urllib.request.install_opener(opener)
# response = urllib.request.urlopen(request)
response = opener.open(request)
print(response.read().decode())
# 打印内容
# with open("proxybaidu.html", 'w') as f:
# f.write(response.read().decode())
# print(response.read().decode())
Cookie
Cookie 是指某些网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。
Cookie原理 HTTP是无状态的面向连接的协议, 为了保持连接状态, 引入了Cookie机制 Cookie是http消息头中的一种属性
from http import cookiejar
import urllib.request
import urllib.parse
# 先创建一个cookiejar对象,用来保存cookie
cookiejar = cookiejar.CookieJar()
# 创建一个能处理cookie的handler
cookie_handler = urllib.request.HTTPCookieProcessor(cookiejar)
# 生成一个opener对象
opener = urllib.request.build_opener(cookie_handler)
# 老登录接口
url = 'http://www.renren.com/PLogin.do'
# 参数
data = {
'email': "496155678@qq.com",
'password': '123456789'
}
# 转成二进制数据 进行传输
params = urllib.parse.urlencode(data).encode()
#构建request
request = urllib.request.Request(url=url,data=params)
#发起请求
opener.open(request)
'''
只要登录成功,自定义的opener就会把登录后的cookie存到cookiejar当中
如果继续发起请求,就会把cookie自动带上
'''
#继续发起请求
request1 = urllib.request.Request(url='http://www.renren.com/966325509/profile')
reponse = opener.open(request1)
with open('cookjarrenren.html','w')as f:
f.write(reponse.read().decode())
网友评论