网络爬虫一课一得

s# 爬取网页数据
基于爬虫得实现原理,进入爬虫得第一阶段:爬取网页数据,即下载包含目标数据的网页。爬取网页需要通过爬虫向服务器发送一个HTTP请求,然后接收服务器返回的响应内容中的整个网页源代码。
利用Python完成这个过程,既可以使用内置的urllib库,也可以使用第三方库requests。使用这两个库,在爬取网页数据时,只需要关心请求的URL格式,要传递什么参数,要设置什么样的请求头,而不需要关心它们的底层是怎么样实现的。下面针对urllib和requests库的使用进行详细讲解。

1 urllib库概述

uurllib库是Python内置的HTTP请求库,它可以看作处理URL的组合集合。urllib库包含四大模块:

  1. urllib.request:请求模块。
  2. urllib.error:异常处理模块。
  3. urllib.parse:URL解析模块。
  4. urllib.robotparser:robts.txt解析模块。

2 快速使用urllib爬取网页

爬取网页其实就是通过URL获取网页信息,这段网页信息的实质就是一段附加了JavaScript和CSS的HTML代码。如果把网页比作一个人,那么HTML就是他的骨架,JavaScript是他的肌肉,CSS是他的衣服。由此看来,网页最重要的数据部分是存在于HTML中的。

2.1 快速爬取一个网页

urllib库的使用比较简单,下面使用urllib快速爬取一个网页,具体代码如下:

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

上述代码就是一个简单的爬取网页案例,爬取的网页结果如下。
在这里插入图片描述
实际上,如果在浏览器上打开百度首页,右击选择“查看页面源代码”命令,就会发现跟刚才打印出来的内容一模一样。也就是说,上述案例仅仅用了几行代码,就把百度首页的全部代码下载下来。

多学一招:Python2使用的是urllib2库
import urllib2
resqonse=urllib2.urlopen('http://www.baidu.com')

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

2.2 分析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)

上述方法定义中的参数详细介绍如下:

  1. url:表示目标资源在网站中的位置,可以是一个表示URL地址的字符串,也可以是一个urllib.request对象。
  2. data:用来指明向服务器发送请求的额外信息。HTTP协议是Python支持的众多网络通信协议(如HTTP、HTTPS、FTP等)中唯一使用data参数的。也就是说,只有打开http网址时,data参数才有作用。除此之外,官方API还指出:
  • data必须是一个bytes对象。
  • data必须符合the standard application/x-www-form-urlencoded format标准。使用urllib.parse.urlencode()可以将自定义的data转换为标准格式
  • data默认为None,此时是以GET方式发送请求,当用户设置data参数时,需要将发送请求的方式改为POST。
  1. timeout:可选参数,该参数用于设置超时时间,单位是秒。
  2. cafile/capath/cadefault:用于实现可信任的CA证书的HTTPS请求,这些参数很少使用。
  3. context:实现SSL加密传输,该参数很少使用。
    下面是data和timeout参数的使用示例,具体如下:
    data参数的使用:
import urllib.request
import urllib.parse
data=bytes(urllib.parse.urlencode({'world':'hello'}).encode(UTF-8))
print(response.read())

timeout参数的使用:

import urllib.request
import urllib.parse
response=urllib.request.urlopen('http://httpbin.org/get',timeout=1)
print(response.read())

2.3 使用HTTPResponse对象

使用urllib。request模块中的urlopen()方法发送HTTP请求后,服务器返回的相应内容封装在一个HTTPResponse类型的对象中。示例代码如下:

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

执行示例代码,其输出结果为:

<class 'http.client.HTTPResponse'>

从输出结果可以看出,HTTPResponse类属于http.client模块,该类提供了获取URL、状态码、响应内容等一系列方法。常见的方法如下:

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

下面使用一段示例代码样式这几个方法的使用,具体如下:

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

执行上述示例代码,其输入结果如下:
在这里插入图片描述

1.4 构造Request对象

当使用urlopen()方法发送一个请求时,如果希望执行更为复杂的操作(如增加HTTP报头),则必须创建一个Request对象来作为urlopen()方法的参数。下面同样以百度首页为例,演示如何使用Request对象来爬取数据。示例代码如下:

import urllib.request
# 将url作为Request()方法的参数,构造并返回一个Request对象
import=urllib.request.Request('http://www.baidu.com')
# 将Request对象作为urlopen()方法的参数,发送给服务器并接收响应
import=urllib.request.urlopen(request)
# 使用read()方法读取获取到的网页内容
html=response.read().decode('UTE-8')
# 打印网页内容
print(html)

上述代码的运行结果和2.1节是完全一样的,只不过代码中间多了一个Request对象。在使用urllib库发送URL时,推荐使用构造Request对象的方式。因为在发送请求时,除了必须设置的url参数外,还可能会加入很多内容,例如下面的参数:

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

下面也是一个构造Request对象的案例。该案例在构造Request对象时传入data和headers参数。具体代码如下:
在这里插入图片描述
上述案例可以实现传智博客官网首页的爬取。通过构造Request对象的方式,服务器会根据发送的请求返回对应的响应内容,这种做法在逻辑上也是非常明确的。

3 使用urllib实现数据传输

在爬取网页时,通过URL传递数据给服务器,传递数据的方式主要分为GET和POST两种。这两种方式最大的区别在于:GET方式是直接使用URL访问,在URL中包含了所有的参数;POST方式则不会再URL中显示所有参数。本节将针对这两种数据传递方式进行讲解。

3.1 URL编码转换

当传递的URL包含中文或者其他特殊字符(例如,空格或“/”等)时,需要使用urllib.parse库中的urlencode()方法将URL进行编码,它可以将key:value这样的键值对转换成“key=value”这样的字符串。示例代码如下:

import urllib.parse
data={
	'a':'传智博客',
	'b':'黑马程序员'
}
result=urllib.parse.urlencode(data)
print(result)

输出结果为:
在这里插入图片描述
反之,解码使用的是url.parse库的unquote()方法,示例代码如下:

import urllib.parse
result=urllib.parse.unquote('a=%E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2%')
print(result)

输出结果为:

a=传智博客

3.2 处理GET请求

GET请求一般用于向服务器获取数据,例如,用百度搜索传智博客(URL是https://www.baidu.com/s?wd=传智博客),浏览器跳转的页面如图所示:
在这里插入图片描述
在这个请求中,“?”后面的字符串就包含了要查询的关键字“传智博客”。下面尝试使用GET方式发送请求,具体代码如下:

import urllib.request
import urllib.parse
url="http://www.baidu.com/s"
word={"wd":"传智博客"}
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"}
request=urllib.request.Request(new_url,headers=headers)
html=response.read().decode('UTF-8')
print(html)

运行程序,程序输出的结果和使用浏览器搜索网页“https://www.baidu.com/s?wd=传智博客”的源代码是一模一样的,由此说明成功爬取了页面。

3.3 处理POST请求

前面分析urlopen()方法时提到过,发送HTTP请求中,如果是以POST方式发送请求,urlopen()方法必须设置data参数。data参数以指点的形式存放数据。
当访问有道词典翻译网站进行词语翻译时,会发现不管输入什么内容,其URL一直都是http://fanyi.youdao.com。通过使用Fiddler观察,发现该网站向服务器发送的请求是POST请求,如图所示。
在这里插入图片描述
从图中可以看出,当使用有道词典翻译"Python"时,返回的结果是一个JSON字符串。下面尝试模拟这个POST请求,具体代码如下:

import urllib.request
import urllib.parse
# POST请求的目标URL
url="http://fanyi.youdao.com/translate? smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null"
headers={"User-Agentv:"Mozilla...."}
# 打开Fiddler请求窗口,点击WebForms选项查看数据体
formdata={
	"tybe":"AUTO",
	"i":"i love python"
	"doctypev:"json",
	"xmlVersion":"1.8",
	"keyfrom":"fanyi.web",
	"ue":"UTF-8",
	"action":"FY_BY_ENTER",
	"typoResult":"true"
}
data=bytes(urllib.parse.urlencode(formdata).encode('UTF-8'))
request=urllib.request.Request(url, data=data, headers=headers)
response=urllib.request.urlopen(request)
print(response.read().decode('utf-8'))

执行上述代码,输出结果如下:
在这里插入图片描述

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值