爬虫003

urllib2的使用

所谓网页抓取,就是把URL地址中指定的网络资源从网络中读取出来,保存到本地或者数据库。在Python中有很多库可以抓取网页,我们先学习urllib2,

1、urllib2是python2.7自带的模块(不需要下载,导入就可以使用)
2、urllib2官网:https://docs.python.org/2/library/urllib2.html
3、urllib2源码:https://hg.python.org/cpython/file/2.7/Lib/urllib2.py
4、urllib2在python3.x中改为urllib.request

目录清单

1、入门小程序(了解爬虫获取数据的步骤和意思)
2、request对象的操作
3、请求头设置——User-Agent代理
4、请求方式(GET和POST)
5、handler处理器和自定义opener
6、会话跟踪(cookie)
7、异常错误处理

1、入门

首先通过一个小程序来认识爬虫

demo01
# -*- coding:utf-8 -*-
#中文注释头

#导入urllib2库
import urllib2

#向指定的url发送请求,并返回服务器响应的类文件对象
response = urllib2.urlopen("http://www.baidu.com")

#类文件对象支持文件对象的操作方法,如read()方法读取文件全部内容,返回字符串
content = response.read()

#打印内容
print content

通过运行,在控制台可以得到百度网页的源码数据

<!doctype html>
<html>
<head>
    <title>百度一下,你就知道</title>
...
...
</html>

实际上,如果我们在浏览器上打开百度首页,右键选择“查看网页源代码”,你会发现,和我们刚刚打印出来的是一模一样。也就是说,上面的4行代码就已经帮我们把百度首页的全部代码爬了下来。

至此,我们就可以说爬虫程序是根据一定的规则采集获取网络上的数据
一个基本的url请求对应的python代码真的非常简单。

2、Request

上述程序我们可以了解爬虫程序的步骤,而底层操作过程是将请求和响应分步进行的

demo02
# -*- coding:utf-8 -*-
#添加注释,指定当前源代码支持中文操作

#导入urllib2库
import urllib2

#url作为request()方法的参数,构造并返回一个request对象
request = urllib2.Request("http://www.baidu.com")

#request对象作为urlopen()方法的参数,发送给服务器并接受响应
response = urllib2.urlopen(request)

content = response.read()

print content

运行结果是完全一样的,

新建的Request,除了url参数外,还可以设置另外两个参数:
1、data(默认为空),是伴随url提交的数据(比如要POST的数据),同时HTTP请求将从"GET"变成"POST"方式
2、headers(默认为空):是一个字典,包含了需要发送HTTP报头的键值对

3、User-Agent

上述代码,爬虫程序已经开发成功并采集数据,如果我们通过抓包工具进行请求查看时,你会发现一个很严重的问题,赤裸裸显示我们的身份是python urllib2的字样,这不是以迅雷不及掩耳之势用爬虫的身份直接访问服务器么,这样略有唐突。就好比你家门没有锁,老王以一个路人的身份直接闯进去,显然是没有礼貌的。而且有些网站不喜欢被程序访问(非人为操作),很容易被服务器进行分析过滤并屏蔽访问。

但是我们以一名合法的身份去请求网站,显然我们就是受欢迎的。所以,我们要对发起请求的爬虫程序进行伪造,就是给我们的代码加上一个身份。可以通过设置请求中的User-Agent来实现

demo03
# -*- coding:utf-8 -*-

import urllib2

url = "http://www.taobao.com"

# IE9.0的User-Agent,包装在header中
headers = {
    "User-Agent": "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"
}

#url和header一起构建request请求,这个请求将附带IE9.0浏览器的User-Agent
request = urllib2.Request(url=url, headers=headers)

response = urllib2.urlopen(request)

content = response.read()

print content

现在就是将爬虫程序发送的请求伪造成浏览器发送的请求,从而让我们拥有一个合法的身份去访问网站

4、请求方式GET和POST

下面我们同两个案列来学习GET和POST

GET方式:

GET请求一般用于我们向服务器获取数据,比如说,我们在百度搜索“黄鹂鸟”:https://www.baidu.com/s?wd=黄鹂鸟

demo04
# -*- coding:utf-8 -*-

# 导入需要的包
from urllib2 import Request, urlopen
from urllib import urlencode

# 定义url地址和访问的数据
url = "http://www.baidu.com/s?"

data = {
    "wd": "黄鹂鸟",
}
#处理完整的请求
fulurl = url + urlencode(data)

request = Request(fulurl)

response = urlopen(request)

print response.read()

POST方式

在Request请求对象里,我们传送data参数,data是一个字典,里面要匹配键值对。通过有道翻译做案例:

demo05
# -*- coding:utf-8 -*-

# 引入需要的模块
from urllib2 import Request, urlopen
from urllib import urlencode
import time
import random
import hashlib

# 真实翻译地址
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

# 处理加密字段
n = raw_input("请输入要翻译的词汇:")
c = "fanyideskweb"
x = "aNPG!!u6sesA>hBAW1@(-"
r = str(int(time.time() * 1000) + random.randint(1, 10))

# 加密字段
sign = hashlib.md5(c + n + r + x).hexdigest()

# 请求头设置
headers = {
    "Accept": "application/json, text/javascript, */*; q=0.01",
    "Origin": "http://fanyi.youdao.com",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
    "Referer": "http://fanyi.youdao.com/",
    "Cookie": "OUTFOX_SEARCH_USER_ID_NCOO=1092450716.3850443; OUTFOX_SEARCH_USER_ID=-1512266810@10.168.1.241; JSESSIONID=aaal2mcR1N1zx5rcovkdw; fanyi-ad-id=39535; fanyi-ad-closed=1; ___rl__test__cookies=1515335942852"
}

# 请求的表单数据
form_data = {
    "i": n,
    "from": "AUTO",
    "to": "AUTO",
    "smartresult": "dict",
    "client": c,
    "salt": r,
    "sign": sign,
    "doctype": "json",
    "version": "2.1",
    "keyfrom": "fanyi.web",
    "action": "FY_BY_REALTIME",
    "typoResult": "false",
}

data = urlencode(form_data)

# 构建请求对象
request = Request(url, data=data, headers=headers)

response = urlopen(request)

print(response.read())

5、自定义的opener对象

  • opener是 urllib2.OpenerDirector 的实例,我们之前一直都在使用的urlopen,它是一个特殊的opener(也就是模块帮我们构建好的)。
  • 但是基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高级功能。所以要支持这些功能:
    1、使用相关的 Handler处理器 来创建特定功能的处理器对象;
    2、然后通过 urllib2.build_opener()方法使用这些处理器对象,创建自定义opener对象;
    3、使用自定义的opener对象,调用open()方法发送请求。
  • 如果程序里所有的请求都使用自定义的opener,可以使用urllib2.install_opener() 将自定义的 opener 对象 定义为 全局opener,表示如果之后凡是调用urlopen,都将使用这个opener(根据自己的需求来选择)

一个简单的自定义opener()

demo06
# -*- coding:utf-8 -*-

import urllib2

# 构建一个HTTPHandler 处理器对象,支持处理HTTP请求
http_handler = urllib2.HTTPHandler()

# 调用urllib2.build_opener()方法,创建支持处理HTTP请求的opener对象
opener = urllib2.build_opener(http_handler)

# 构建 Request请求
request = urllib2.Request("http://www.baidu.com/")

# 调用自定义opener对象的open()方法,发送request请求
response = opener.open(request)

print response.read()

ProxyHandler处理器(代理设置)

使用代理IP,这是爬虫/反爬虫的大招,通常也是最好用的。
在反爬的操作过程中,有一种反爬虫操作是针对出现异常访问量的ip地址进行封锁的操作,如果使用自己的真实ip地址访问,很有可能导致自己的ip地址被封,就会禁止访问这个网站。
所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算一个ip地址被封,我们还有千千万万个ip可以使用。

demo07
# -*- coding:utf-8 -*-

import urllib2

# 创建代理处理器
proxy_handler = urllib2.ProxyHandler({'http': '61.135.217.7:80'})

# 创建Opener对象
proxy_opener = urllib2.build_opener(proxy_handler)

# 打开指定的网址
response = proxy_opener.open("https://www.taobao.com")

print response.read()

免费的开放代理获取基本没有成本,我们可以在一些网站上收集这些免费代理,测试后如果可以用,就把它们收集起来用在爬虫上面。免费短期代理网站举例:

6、会话跟踪

在很多网站上,都使用了基于cookie的会话跟踪技术。什么是cookie?cookie是指某些网站服务为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。

在进行爬虫的操作当中,我们会经常使用cookie的操作。对于cookie,最原始的方法就是在请求头中设置cookie的字段,通过抓包工具给cookie设置了固定不变的字段,在实际中,cookie是频繁不断的在变化。

python提供了cookielib库,该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。
可以很方便的实现cookie的数据操作。其实大多数情况下,我们只用CookieJar(),如果需要和本地文件交互,就用 MozillaCookjar() 或 LWPCookieJar()

demo08
  • 首先获取访问网站的cookie值
# -*- coding:utf-8 -*-

import urllib2
import cookielib

# 创建一个基于cookie核心操作对象
cookie = cookielib.CookieJar()

#一个基于cookie的对象
handler = urllib2.HTTPCookieProcessor(cookie)

# 可以操作cookie的opener对象
opener = urllib2.build_opener(handler)

# 打开目标网站
response = opener.open("http://fanyi.youdao.com")

# 查看cookie数据
for i in cookie:
    print i.name + "--" + i.value

  • 将访问到的cookie保存到本地
# -*- coding:utf-8 -*-

import urllib2
import cookielib

cookie = cookielib.MozillaCookieJar("youdao.txt")

handler = urllib2.HTTPCookieProcessor(cookie)

opener = urllib2.build_opener(handler)

response = opener.open("http://fanyi.youdao.com")

# 保存cookie到文件
cookie.save()
  • 从本地加载cookie数据
# -*- coding:utf-8 -*-

import urllib2
import cookielib

cookie = cookielib.MozillaCookieJar()

# 加载cookie中的数据
cookie.load("youdao.txt")

handler = urllib2.HTTPCookieProcessor(cookie)

opener = urllib2.build_opener(handler)

response = opener.open("http://fanyi.youdao.com")
# 完整代码参考post请求

7、异常处理

urllib2的异常错误处理。这里我们主要说URLError和HTTPError,以及对他们的错误处理

URLError

URLError产生的主要原因:

1、没有网络连接
2、服务器连接失败
3、找不到指定的服务器

我们可以使用 try except语句来捕获响应的异常,下面我们访问一个不存在的域名:

demo09
# -*- coding:utf-8 -*-

import urllib2

request = urllib2.Request("http://www.lovehuangliniao.com")

try:
    urllib2.urlopen(request, timeout=3)
except urllib2.URLError, err:
    print err

运行结果就是没有找到指定的服务器

<urlopen error [Errno 8] nodename nor servname provided, or not known>
HTTPError

HTTPError是URLError错误的子类,发送一个请求时,在服务器上就会产生一个相对应的response相应对象,里面包含一个数字“响应状态码”。
响应状态码

如果urlopen或opener.open不能处理的,会产生一个HTTPError,对应相应的状态码,HTTP状态码表示HTTP协议所返回的响应的状态。

demo10
# -*- coding:utf-8 -*-

import urllib2

request = urllib2.Request("http://www.dailiyun.com/huang")

try:
    response = urllib2.urlopen(request)
except urllib2.HTTPError, err:
    print err.code
    print err

运行结果:

404
HTTP Error 404: Not Found

HTTP Error,错误代号是404,错误原因是Not Found,说明服务器无法找到被请求的页面。
通常产生这种错误的,要么url不对,要么ip被封。

通过上述内容,可以把urllib2的基本知识掌握,就可以肆无忌惮的去获取你想要的数据。

课堂小作业,可以爬取贴吧内容,豆瓣电影上的电影名称,评分等等

书写不易,小哥哥小姐姐留个赞或关注。3Q

看了我的文,就是我的人。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容