您的位置:首页 > 编程语言 > Python开发

Python 爬虫学习稿(一)

2016-01-10 00:52 591 查看
本次学习的环境是基于Python 3.3.5,实验的工具是Pycharm 5.0.1

基础的知识我就不再介绍,比如HTTP的基础知识、爬虫的相关背景

直接开始爬虫的学习吧!

一、用Python抓取指定页面

常见的urllib2库在Python3.X的版本中改名啦!叫urllib.request了!

urlopen()可以接收三个参数即
urlopen(url, data, timeout)


url即你要请求的url地址,data是访问这个url需要传送的数据,timeout是超时时间

url是必填参数,其余两个是可选参数

urllib.request.urlopen(url)会返回一个http.client.HTTPResponse对象

这个返回的对象可以使用read()方法,来返回数据

# encoding: utf-8

import urllib.request

response = urllib.request.urlopen("http://www.baidu.com")
print(response.read())


这样一个脚本就可以让我们得到所填入的
www.baidu.com
这个网址的网页源码,你可以开启浏览器,然后按下F12来对照看是不是一样

如果我们不调用read这个方法,会打印出什么呢?会打印出下面这样一行

<http.client.HTTPResponse object at 0x0314B690>


这样就直接把这个对象的描述打印出来了,而不是具体内容了

二、构造Request

根据我们的习惯,我们应该当传入一个request的实例,我们可以改写上面的代码为

# encoding: utf-8

import urllib.request

request = urllib.request.Request("http://www.baidu.com")
response = urllib.request.urlopen(request)
print(response.read())


这样也是完全相同的效果,我们必须注意的是库是区分大小写的,Request写成request是不能被识别的,会报错

这样我们就完成了构建一个request,然后得到服务器对请求的应答,这样更符合直观的逻辑

需要说明的是,urllib.request.Request()是统一处理所有URL头的方法,你可以直接使用
ftp://baidu.com
也是可以的

三、传递表单数据

Web传递表单数据的常见方式有POST和GET两种方式,我们可以构造一个表单作为data,然后编码成标准形式,作为参数传递给Request对象

值得注意的是,编码所使用的库为urllib的函数而不是像之前的程序可以只引用一个urllib2库就可以了,Python 3.X的版本和和之前的2.X的版本差距还是真大

遇到这个错误
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str
时,是需要在url编码后再使用utf-8进行编码,否则会出现这个类型错误。修改方法是)
urllib.parse.urlencode(values).encode(encoding='UTF8')


还必须指出的是,在Python 2.X中所使用的urllib.urlencode并不存在了,只能使用
urllib.parse.urlencode
进行替换

代码如下

# encoding: utf-8
import urllib
import urllib.request

value = {"username" : "teacher" , "password" : "123456789"}
data = urllib.parse.urlencode(value).encode(encoding='UTF8')
url = "http://mail.qinghua.edu.cn/login?"
request = urllib.request.Request(url , data)
response = urllib.request.urlopen(request)
print(response.read())


你需要替换成一个你可以登录的URL地址,就可以进行测试了,或者你可以在本地自己搭建一个最简单的CGI脚本来进行测试

上面这个方法是使用POST来进行传递表单数据时,下面介绍GET如何进行表单数据的传送

# encoding: utf-8
import urllib
import urllib.request

value = {"username" : "teacher" , "password" : "123456789"}
data = urllib.parse.urlencode(value).encode(encoding='UTF8')
url = "http://mail.qinghua.edu.cn/login"
geturl = url + "?" + data
request = urllib.request.Request(geturl)
response = urllib.request.urlopen(request)
print(response.read())


Python3对文本和二进制数据作了更为清晰的区分。文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示,二者不能混用。

所以你如果这样执行的话,必然遇到错误
TypeError: Can't convert 'bytes' object to str implicitly
因为此时的data是byte型的,而url是str型的,两者不能连接起来的,需要把byte型的data转换成str型

# encoding: utf-8
import urllib
import urllib.request

value = {"username" : "teacher" , "password" : "123456789"}
data = urllib.parse.urlencode(value).encode(encoding='UTF8')
url = "http://mail.qinghua.edu.cn/login"
geturl = url + "?" + data.decode()
request = urllib.request.Request(geturl)
response = urllib.request.urlopen(request)
print(response.read())


使用.decode()进行解码,就能将byte型的data转换成str型,geturl就统一为str型就可以进行连接了。这样就可以成功执行了,只不过同上一个一样,你需要找一个能够成功的 URL地址

四、设置Headers构建HTTP请求

我们都知道,对不同的浏览器,网页端可以进行分别适配以达到最佳的浏览体验,还有一些像微信中的某些连接只能用微信中的浏览器打开的,如果你用电脑的浏览器就无法打开,所以我们可以对Headers头进行设置来构建HTTP请求

浏览器会把自己的标识发给服务器,但是urllib默认是显示python-urllib,这样会导致服务器不予以响应,那么我们可以显式的指定headers里的字段,下面列举了常见的一些字段:

User-Agent : 有些服务器或 Proxy 会通过该值来判断是否是浏览器发出的请求

Content-Type : 在使用 REST 接口时,服务器会检查该值,用来确定 HTTP Body 中的内容该怎样解析。在使用服务器提供的 RESTful 或 SOAP 服务时, Content-Type 设置错误会导致服务器拒绝服务

application/xml : 在 XML RPC,如 RESTful/SOAP 调用时使用

application/json : 在 JSON RPC 调用时使用

application/x-www-form-urlencoded : 浏览器提交 Web 表单时使用

所以我们修改一个User-Agent作为范例

# encoding: utf-8
import urllib
import urllib.request

user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
value = {"username" : "teacher" , "password" : "123456789"}
data = urllib.parse.urlencode(value).encode(encoding='UTF8')
headers = {'User-Agent' : user_agent}
url = "http://mail.qinghua.edu.cn/login?"
request = urllib.request.Request(url , data, headers)
response = urllib.request.urlopen(request)
print(response.read())


还可以继续修改Referer,这样可以反反盗链

# encoding: utf-8
import urllib
import urllib.request

user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
value = {"username" : "teacher" , "password" : "123456789"}
data = urllib.parse.urlencode(value).encode(encoding='UTF8')
headers = {'User-Agent' : user_agent , 'Referer': 'http://mail.qinghua.edu.cn/'}
url = "http://mail.qinghua.edu.cn/login?"
request = urllib.request.Request(url , data, headers)
response = urllib.request.urlopen(request)
print(response.read())


五、关于其他

timeout的设置,如果有的网站响应速度过慢,可以通过设置timeout来避免无限制等待响应,之前也说过,urlopen的第三个参数就是timeout,显式设置即可

有时候不得不使用代理服务器来避免一个IP访问请求过多遭到禁止,那么如何设置代理就是一门学问,这里简明写个小例子

# encoding: utf-8

import urllib.request
enable_proxy = True
proxy_handler = urllib.request.ProxyHandler({"http" : 'http://some-proxy.com:8080'})
null_proxy_handler = urllib.request.ProxyHandler({})
if enable_proxy:
opener = urllib.request.build_opener(proxy_handler)
else:
opener = urllib.request.build_opener(null_proxy_handler)
urllib.request.install_opener(opener)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: