爬虫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

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




    百度一下,你就知道
...
...

实际上,如果我们在浏览器上打开百度首页,右键选择“查看网页源代码”,你会发现,和我们刚刚打印出来的是一模一样。也就是说,上面的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; [email protected]; 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()

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

  • 西刺免费代理IP
  • 快代理免费代理
  • Proxy360代理
  • 全网代理IP
    如果代理IP足够多,就可以像随机获取User-Agent一样,随机选择一个代理去访问网站,提高了获取数据的效率。

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

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


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

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

你可能感兴趣的:(爬虫003)