Urllib发送请求

基本用法

基本的用法就是调用request库,

class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)在编写代码之前把这些属性值填写成自己想要的参数就行了,

高级用法

将介绍“处理器“---Handler。利用它就可以处理Cookies、设置代理等任何HTTP请求中所有的事情。

首先介绍下 urllib.request 模块里的 BaseHandler类,它是所有其他 Handler 的父类,它提供了最基本的 Handler 的方法,例如 default_open()、protocol_request() 方法等。接下来就有各种 Handler 子类继承这个 BaseHandler 类,举例几个如下:

  • HTTPDefaultErrorHandler 用于处理 HTTP 响应错误,错误都会抛出 HTTPError 类型的异常。
  • HTTPRedirectHandler 用于处理重定向。
  • HTTPCookieProcessor 用于处理 Cookies。
  • ProxyHandler 用于设置代理,默认代理为空。
  • HTTPPasswordMgr 用于管理密码,它维护了用户名密码的表。
  • HTTPBasicAuthHandler 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。

    更多的Handler可以参考https://docs.python.org/3/library/urllib.request.html#basehandler-objects

    在正常的request中需要使用urlopen,而handler则是需要使用Opener,urlopen()这个方法就是Urllib为我们提供的一个Opener。

认证

有些网站必须要输入用户名和密码,认证成功后才能继续显示。类似的网站比如路由器的管理员登录界面(在浏览器中输入192.168.1.1跳转的界面)。在这里并不是绕过登录界面,而是在模拟请求的时候不会报错。

from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLError username = 'username'
password = 'password'
url = 'http://localhost:5000/' p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
auth_handler = HTTPBasicAuthHandler(p)
opener = build_opener(auth_handler) try:
result = opener.open(url)
html = result.read().decode('utf-8')
print(html)
except URLError as e:
print(e.reason)

代理

设置代理

from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener proxy_handler = ProxyHandler({
'http': 'http://127.0.0.1:9743',
'https': 'https://127.0.0.1:9743'
})
opener = build_opener(proxy_handler)
try:
response = opener.open('https://www.baidu.com')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)

Cookie

首先花点时间介绍一下Cookies,登录网站的时候我们常常会发现有些网站自动登录了,而且很长时间都不会失效、有些则是需要我们重新登录(输入用户模型和密码的),这其实涉及到了Session和Cookies的相关知识。HTTP协议是一种无状态的协议,意思是客户端与服务端进行数据交互的时候并不会保存进行的操作,举个例子:当我们加载网页的一张图片,传过来只有半张时停止加载,我们如果不加处理的再去向服务器请求,服务端是不会记住之前传输的操作的,服务端所进行的操作是重新将这张图片完整的数据重新传输一次。所以,HTTP 的无状态是指 HTTP 协议对事务处理是没有记忆能力的,也就是说服务器不知道客户端是什么状态。。这点虽然避免了信息的冗余性(不会要求HTTP协议在进行数据传输时仍然要保存事务处理),但是对于需要用户登录的页面来说,为了保持前后状态,我们肯定不希望将前面的请求全部重传一次,这样过于浪费资源了,所以保持HTTP连接状态的技术就出现了。Session在服务端(网站的服务器),用于保存用户的会话信息,Cookies在客户端。服务器通过识别 Cookies 并鉴定出是哪个用户,然后再判断用户是否是登录状态,然后返回对应的 Response。所以,我们可以这样理解:如果我们将一次登陆成功后的Cookies放在Request Headers里面直接请求服务端,就不必重新模拟登陆了。

当浏览器下一次再请求该网站时,浏览器会把此Cookies 放到 Request Headers 一起提交给服务器,Cookies 携带了 Session ID 信息,服务器检查该 Cookies 即可找到对应的 Session 是什么,然后再判断 Session 来以此来辨认用户状态。所以我们在登录某个网站的时候,登录成功后服务器会告诉客户端设置哪些 Cookies 信息,在后续访问页面时客户端会把 Cookies 发送给服务器,服务器再找到对应的 Session 加以判断,如果 Session 中的某些设置登录状态的变量是有效的,那就证明用户是处于登录状态的,即可返回登录之后才可以查看的网页内容,浏览器进行解析便可以看到了。

好了,下面我们介绍python中与Cookies相关的Handler,首先将网站的Cookies获取下来:

import http.cookiejar, urllib.request

cookie = http.cookiejar.CookieJar()    #申明一个CookieJar对象
handler = urllib.request.HTTPCookieProcessor(cookie) #创建Handler
opener = urllib.request.build_opener(handler) #构建出Opener
response = opener.open('http://www.baidu.com') #执行open()函数
for item in cookie:
print(item.name+"="+item.value)

执行的结果如下:

BAIDUID=2E65A683F8A8BA3DF521469DF8EFF1E1:FG=1
BIDUPSID=2E65A683F8A8BA3DF521469DF8EFF1E1
H_PS_PSSID=20987_1421_18282_17949_21122_17001_21227_21189_21161_20927
PSTM=1474900615
BDSVRTM=0
BD_HOME=0

以上就是Cookies的完整样貌,我们可以将这个Cookie保存下来方便我们后面调用:

filename = 'cookies.txt'
#cookie = http.cookiejar.MozillaCookieJar(filename)
cookie = http.cookiejar.LWPCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)

这时的 CookieJar就需要换成 MozillaCookieJar,生成文件时需要用到它,它是 CookieJar 的子类,可以用来处理 Cookies 和文件相关的事件,读取和保存 Cookies,它可以将 Cookies 保存成 Mozilla 型浏览器的 Cookies 的格式。

生成的cookies.txt文件如下:

#LWP-Cookies-2.0
Set-Cookie3: BAIDUID="0CE9C56F598E69DB375B7C294AE5C591:FG=1"; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2084-10-14 18:25:19Z"; version=0
Set-Cookie3: BIDUPSID=0CE9C56F598E69DB375B7C294AE5C591; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2084-10-14 18:25:19Z"; version=0
Set-Cookie3: H_PS_PSSID=20048_1448_18240_17944_21089_21192_21161_20929; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0
Set-Cookie3: PSTM=1474902671; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2084-10-14 18:25:19Z"; version=0
Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
Set-Cookie3: BD_HOME=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0

接下来利用Cookies的LWPCookieJar格式来读取文件:

cookie = http.cookiejar.LWPCookieJar()
cookie.load('cookies.txt', ignore_discard=True, ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
print(response.read().decode('utf-8')

Urllib处理异常

在跑程序获取数据中,如果程序中途遇到错误而我们没有写异常处理的时候,尽可能辛辛苦苦跑的数据就损失了;在获取豆瓣电影top250的时候,部分电影的参数不完整,导致爬虫总是会在这中途出现错误。。。更有可能的是,如果网络情况突然变更,要做异常处理,是的网络恢复的时候能继续运行程序。综上,写异常处理真的非常重要!!

HTTPError

  • code,返回 HTTP Status Code,即状态码,比如 404 网页不存在,500 服务器内部错误等等。
  • reason,同父类一样,返回错误的原因。
  • headers,返回 Request Headers。
from urllib import request,error
try:
response = request.urlopen('http://没有这个页面.com/index.htm')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, seq='\n')

Python网络爬虫(一)的更多相关文章

  1. 关于Python网络爬虫实战笔记③

    Python网络爬虫实战笔记③如何下载韩寒博客文章 Python网络爬虫实战笔记③如何下载韩寒博客文章 target:下载全部的文章 1. 博客列表页面规则 也就是, http://blog.sina ...

  2. 关于Python网络爬虫实战笔记①

    python网络爬虫项目实战笔记①如何下载韩寒的博客文章 python网络爬虫项目实战笔记①如何下载韩寒的博客文章 1. 打开韩寒博客列表页面 http://blog.sina.com.cn/s/ar ...

  3. python 网络爬虫(二) BFS不断抓URL并放到文件中

    上一篇的python 网络爬虫(一) 简单demo 还不能叫爬虫,只能说基础吧,因为它没有自动化抓链接的功能. 本篇追加如下功能: [1]广度优先搜索不断抓URL,直到队列为空 [2]把所有的URL写 ...

  4. python网络爬虫学习笔记

    python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...

  5. Python网络爬虫

    http://blog.csdn.net/pi9nc/article/details/9734437 一.网络爬虫的定义 网络爬虫,即Web Spider,是一个很形象的名字. 把互联网比喻成一个蜘蛛 ...

  6. Python 正则表达式 (python网络爬虫)

    昨天 2018 年 01 月 31 日,农历腊月十五日.20:00 左右,152 年一遇的月全食.血月.蓝月将今晚呈现空中,虽然没有看到蓝月亮,血月.月全食也是勉强可以了,还是可以想像一下一瓶蓝月亮洗 ...

  7. Python网络爬虫笔记(五):下载、分析京东P20销售数据

    (一)  分析网页 下载下面这个链接的销售数据 https://item.jd.com/6733026.html#comment 1.      翻页的时候,谷歌F12的Network页签可以看到下面 ...

  8. 如何利用Python网络爬虫抓取微信朋友圈的动态(上)

    今天小编给大家分享一下如何利用Python网络爬虫抓取微信朋友圈的动态信息,实际上如果单独的去爬取朋友圈的话,难度会非常大,因为微信没有提供向网易云音乐这样的API接口,所以很容易找不到门.不过不要慌 ...

  9. 如何利用Python网络爬虫爬取微信朋友圈动态--附代码(下)

    前天给大家分享了如何利用Python网络爬虫爬取微信朋友圈数据的上篇(理论篇),今天给大家分享一下代码实现(实战篇),接着上篇往下继续深入. 一.代码实现 1.修改Scrapy项目中的items.py ...

  10. 【python网络爬虫】之requests相关模块

    python网络爬虫的学习第一步 [python网络爬虫]之0 爬虫与反扒 [python网络爬虫]之一 简单介绍 [python网络爬虫]之二 python uillib库 [python网络爬虫] ...

随机推荐

  1. WEBRTC基本介绍

    “WebRTC,名称源自网页实时通信(Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的技术,是谷歌2010年以6820万美元收购Glob ...

  2. ACM学习历程—广东工业大学2016校赛决赛-网络赛E 积木积水(最值问题 || 动态规划)

    题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=4 这个题目自然会考虑到去讨论最长或者最短的板子. 笔上大概模拟一下的话,就 ...

  3. bzoj 2733 永无乡 线段树

    题目: 支持两种操作: 合并两点所在的联通块 查询某点所在联通块内权值第k小. 题解 平衡树启发式合并随便搞一搞就好了. 我写了一个线段树合并 #include <cstdio> #inc ...

  4. Access中创建子数据表/主子数据表

    摘 要:我们为什么要使用Access,而不用Excel,因为数据库可以大幅度地消除冗余数据,其方法就是将数据拆分到不同的表中,再通过“关系”建立表间的联系.那么如何确定表间的关系呢.表之间的关系是通过 ...

  5. http头部解释

    If-Modified-Since,If-Node-Match,ETag,Last-Modified 1 属于 Request Headers的是:If-Modified-Since,If-Node- ...

  6. 使用Rancher搭建K8S测试环境

    使用Rancher搭建K8S测试环境 http://blog.csdn.net/csdn_duomaomao/article/details/75316926 环境准备(4台主机,Ubuntu16.0 ...

  7. 安装mariadb并修改配置文件

    实验环境:CentOS7 #安装mariadb-server包#修改mariadb配置文件/etc/my.cnf.d/server.cnf#添加 skip_name_resolve=ON #不执行将I ...

  8. 在python3.6下 发明一个类似python3.7 dataclass数据类,不用在 __init__中self.xx

    虽然我用3.6,但我在2.7转3.6时候,把3.3 3.4 3.5 3.6的变化都看了一次,虽然已经忘了哪些变化.同时也关注3.7 3.8的变化,3.7中就有1个数据类印象深刻,因为之前在定义这种类时 ...

  9. nodejs利用windows API读取文件属性(dll)

    nodejs调用delphi编写的dll中,使用了dll调用windows api转读取文件属性,感觉使用nodejs也可直接调用windows api. 此处需用到windows系统的version ...

  10. j++与++j

    (j++)+(++j)+(++j) 核心部分汇编代码 执行顺序j原始值为5,存放在栈的ebp-4中;q无初始值,存放在栈的ebp-8中先执行一次j自增赋值++j ;j=6执行第一个加法运算;值存放在C ...