Python爬虫基础

目录

一、什么是urllib库

二、使用urllib快速爬取网页

三、分析urlopen方法

四、使用HTTPResponse对象

五、构造Request对象

六、URL编码转换

七、处理GET请求(明文)

八、处理POST请求(密文)

九、添加特定Headers—请求伪装

十、代理服务器

十一、超时设置

十二、URLError异常和捕获

十三、什么是requests库


一、什么是urllib库

urllib库是Python内置的HTTP请求库,它可以看做是处理URL的组件集合。

二、使用urllib快速爬取网页

import urllib.request
# 调用urllib.request库的urlopen方法,并传入一个url 
response = urllib.request.urlopen('http://www.baidu.com')
# 使用read方法读取获取到的网页内容
html = response.read().decode('UTF-8')
# 打印网页内容
print(html)

上述案例仅仅用了几行代码,就已经帮我们把百度的首页的全部代码下载下来了。

实际上,如果我们在浏览器上打开百度主页,右键选择“查看源代码”,你会发现,跟我们刚才打印出来的是一模一样。

Python2中使用的是urllib2库来下载网页,该库的用法如下所示:

import urllib2
response = urllib2.urlopen('http://www.baidu.com')

Python3出现后,之前Python2中的urllib2库被移到了urllib.request模块中,之前urllib2中很多函数的路径也发生了变化,希望大家在使用的时候多加注意。

三、分析urlopen方法

前面在爬取网页时,有一句核心的爬虫代码:

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

上述代码调用的是urllib.request模块中的urlopen方法,它传入了一个百度首页的URL,使用的协议是HTTP,这是urlopen方法最简单的用法。

urlopen方法可以接收多个参数,定义格式如下:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

参数如下:
 url -- 表示目标资源在网站中的位置。
 data -- 用来指明向服务器发送请求的额外信息。
 timeout -- 该参数用于设置超时时间,单位是秒。
 context -- 实现SSL加密传输,该参数很少使用。

四、使用HTTPResponse对象

使用urlopen方法发送HTTP请求后,服务器返回的响应内容封装在一个HTTPResponse类型的对象中。

<class 'http.client.HTTPResponse'>

import urllib.request
response = urllib.request.urlopen('http://www.itcast.cn')
print(type(response))

HTTPResponse类属于http.client模块,该类提供了获取URL、状态码、响应内容等一系列方法。

 geturl() -- 用于获取响应内容的URL,该方法可以验证发送的HTTP请求是否被重新调配。
 info() -- 返回页面的元信息。
 getcode() -- 返回HTTP请求的响应状态码。

import urllib.request
response = urllib.request.urlopen('http://python.org')
# 获取响应信息对应的URL
print(response.geturl())
# 获取响应码
print(response.getcode())
# 获取页面的元信息
print(response.info())

五、构造Request对象

如果希望对请求执行复杂操作,则需要创建一个Request对象来作为urlopen方法的参数。

# 将url作为Request方法的参数,构造并返回一个Request对象
request = urllib.request.Request('http://www.baidu.com')
# 将Request对象作为urlopen方法的参数,发送给服务器并接收响应
response = urllib.request.urlopen(request)

在使用urllib库发送URL的时候,我们推荐大家使用构造Request对象的方式(方便后续操作)。

在构建请求时,除了必须设置的url参数外,还可以加入很多内容,例如下面的参数:

参数如下:
 data    -- 默认为空,该参数表示提交表单数据,同时HTTP请求方法将从默认的GET方式改为POST方式。
 headers -- 默认为空,该参数是一个字典类型,包含了需要发送的HTTP报头的键值对。


六、URL编码转换

当传递的URL中包含中文或者其它特殊字符(如空格等)时,需要使用urllib.parse库中的urlencode方法将URL进行编码,

data={"a":"会飞的香猪","b":"好程序员"}

转码---->a=%E4%BC%9A%E9%A3%9E%E7%9A%84%E9%A6%99%E7%8C%AA&b=%E5%A5%BD%E7%A8%8B%E5%BA%8F%E5%91%98

它可以将“key:value”这样的键值对转换成“key=value”这样的字符串。

解码使用的是url.parse库的unquote方法。

import urllib.parse
data={"a":"会飞的香猪","b":"好程序员"}


#编码
text =urllib.parse.urlencode(data)
print(text)


#解码
entext=urllib.parse.unquote(text)
print(entext)

a=会飞的香猪

七、处理GET请求(明文)

GET请求一般用于向服务器获取数据,比如说,我们用百度搜会飞的香猪

此时,如果使用Fiddler查看HTTP请求,发现有个GET请求的格式如下

https://www.baidu.com/s?wd=%E4%BC%9A%E9%A3%9E%E7%9A%84%E9%A6%99%E7%8C%AA

在这个请求中,“?”后面的字符串就包含了我们要查询的关键字“会飞的香猪”。

八、处理POST请求(密文)

当访问有道词典翻译网站进行词语翻译时,会发现不管输入什么内容,其URL一直都是不变的。

通过使用Fiddler观察,发现该网站向服务器发送的是POST请求。

 当使用有道词典翻译“Python”时,返回的结果是一个JSON字符串。

九、添加特定Headers—请求伪装

如果不是从浏览器发出的请求,我们是不能获得响应内容的。针对这种情况,我们需要将爬虫程序发出的请求伪装成一个从浏览器发出的请求。

伪装浏览器需要自定义请求报头,也就是在发送Request请求时,加入特定的Headers

可通过cmd查看是否有Request库

没有可以通过命令C:\Users\Administrator>pip3 install requests

进行下载

user_agent = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT6.1; Trident/5.0)"}
request = urllib.request.Request(url, headers = user_agent)
request.add_header("Connection", "keep-alive")

import requests
url="http://www.baidu.com/s"
param={"wd":"电影评分"}
#设置请求头
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"}
reponse =requests.get(url,param,headers=headers)
#查看响应内容
print(reponse.status_code)
print(reponse.content.decode("UTF-8"))

十、代理服务器

很多网站会检测某一段时间某个IP的访问次数,如果同一IP访问过于频繁,那么该网站会禁止来自该IP的访问。碰到这种情况要怎么办呢?

简单的自定义opener

我们可以使用代理服务器,每隔一段时间换一个代理。如果某个IP被禁止,那么就可以换成其他IP继续爬取数据,从而可以有效解决被网站禁止访问的情况。

opener是urllib.request.OpenerDirector类的对象,我们之前一直都在使用的urlopen,就是模块帮我们构建好的一个opener。

但是,urlopen不支持代理、Cookie等其他的 HTTP/HTTPS高级功能,所以如果要想设置代理,不能使用自带的urlopen,而是要自定义opener。

自定义opener需要执行下列三个步骤:

如果程序里所有的请求都使用自定义的opener,可以使用urllib2.install_opener() 将自定义的opener对象定义为全局opener,表示之后凡是调用urlopen,都将使用自定义的opener。


十一、超时设置

假设我们要爬取1000个网站,如果其中有100个网站需要等待30s才能返回数据,则要返回所有的数据,至少需要等待3000秒

我们可以为HTTP请求设置超时时间,一旦超过这个时间,服务器还没有返回响应内容,那么就会抛出一个超时异常,这个异常需要使用try语句来捕获。

<urlopen error timed out>

try:
       url = 'http://218.56.132.157:8080'  
       # timeout设置超时的时间          
       file = urllib.request.urlopen(url, timeout=1)           
       result = file.read()        
       print(result)
except Exception as error:            
       print(error)

十二、URLError异常和捕获

URLError产生的原因主要有:

HTTPError是URLError的子类,它的对象拥有一个整型的code属性,表示服务器返回的错误代码。

import urllib.request

request = urllib.request.Request('http://www.baidu.cn/test')
try:
        urllib.request.urlopen(request)
except urllib.error.HTTPError as e:
        print(e.code)

上述输出了404的错误码,其含义是没有找到这个页面。

状态码200(成功)  服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。

十三、什么是requests库

requests是基于Python开发的HTTP 库,与urllib标准库相比,它不仅使用方便,而且能节约大量的工作。

其中,Request类的对象表示一个请求,它的生命周期针对一个客户端请求,一旦请求发送完毕,该请求包含的内容就会被释放掉。而Session类的对象可以跨越多个页面,它的生命周期同样针对的是一个客户端。

urllib发送get请求

# 导入请求和解析模块
import urllib.request
import urllib.parse
# 请求的URL路径和查询参数
url = "http://www.baidu.com/s"
word = {"wd":"千锋教育"}
# 转换成url编码格式(字符串)
word = urllib.parse.urlencode(word)
# 拼接完整的URL路径
new_url = url + "?" + word

# 请求报头
headers ={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}
# 根据URL和headers构建请求
request = urllib.request.Request(new_url, headers = headers)
# 发送请求,并接收服务器返回的文件对象
response = urllib.request.urlopen(request)
# 使用read方法读取获取到的网页内容,使用UTF-8格式进行解码
html = response.read().decode('UTF-8')
print(html)

requests发送get请求

import requests
url="http://www.baidu.com/s"
param={"wd":"电影评分"}
#设置请求头
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"}
reponse =requests.get(url,param,headers=headers)
#查看响应内容
print(reponse.status_code)
print(reponse.content.decode("UTF-8"))

接下来,我们再从细节上体会一下requests库的便捷之处,具体如下:

无须再转换为URL路径编码格式,拼接完整的URL路径。
无须再频繁地为中文转换编码格式。
从发送请求的函数名称,可以很直观地判断发送到服务器的方式。

requests库中提供了很多发送HTTP请求的函数。

这些函数都会做两件事情,一件是构建一个Request类的对象,该对象将被发送到某个服务器上请求或者查询一些资源;另一件是一旦得到服务器返回的响应,就会产生一个Response对象,该对象包含了服务器返回的所有信息,也包括原来创建的Request对象。

Response类用于动态地响应客户端的请求,控制发送给用户的信息,并且将动态地生成响应,包括状态码、网页的内容等。

当请求发出之后,Requests库可以找出它使用了什么编码,并且可以设置encoding 属性进行改变。

>>> response.encoding
'utf-8'
>>> response.encoding = 'ISO-8859-1'

再次调用text属性获取返回的文本内容时,将会使用上述设置的新的编码方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Keep Doing this

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值