爬 虫 基 础

网络爬虫工作流程中的第一步就是爬取网页,只有爬取网页获得了网页的源代码,才能提取其中的有效信息。而爬取网页首先就需要向Web服务器发送构造的HTTP请求,从而获得包含所需数据的HTTP响应。 本章从HTTP基本原理入手,介绍网络爬虫爬取网页的基础知识,包括HTTP请求和HTTP响应、urllib库、requests库和字符编码等内容。

目录

 1  HTTP基本原理

2  urllib库

3  requests库

4  字符编码


注:小节没分好,内容很多,慢慢看,一定要自己上手练,不懂可以发私信问。

 1  HTTP基本原理

在浏览器中输入一个URL,按回车键后便会在浏览器中显示网页内容。

实际上,这个过程是浏览器向Web服务器发送了一个HTTP请求;

Web服务器接收到这个请求后进行解析和处理,然后返回给浏览器对应的HTTP响应;

浏览器再对HTTP响应进行解析,从而将网页呈现了出来。

使用Google Chrome浏览器打开百度的搜索页面为例来展示HTTP请求和响应的过程。(edge也行)

打开Google Chrome浏览器,右击页面空白处,在弹出的快捷菜单中选择“检查”选项,打开浏览器的开发者工具窗口,然后选择“Network”选项。访问https://www.baidu.com/,即可在开发者工具窗口中显示请求记录,其中每一条记录都代表一次发送请求和接收响应的过程。

 

 在记录列表中,选择“www.baidu.com”选项,然后在其右侧打开的界面中选择“Headers”选项,即可显示HTTP请求和响应的详细信息,

 

请求的网址(Request URL) 

请求方法(Request Method)

常见的请求方法有两种:GET方法和POST方法。 (1)GET方法,请求指定的网页信息,并返回网页内容,提交的数据最多只有1024字节。 (2)POST方法,向指定资源提交数据并进行请求处理(如提交表单或上传文件)。数据都包含在请求体中,提交的数据没有字节限制。

请求头(Request Headers)

请求头(Request Headers)

 “Request Method”部分即为请求方法(GET方法)。可以看出,平时打开网站一般使用的是GET方法,也就是请求页面; 如果是向网站提交数据(如登录网站),就用到了POST方法。还有一些其他的请求方法,如HEAD、PUT、DELETE、CONNECT、OPTIONS和TRACE等,在实际编写爬虫程序时很少用到

2  urllib库

urllib库是Python内置的标准库,不需要额外安装即可使用,它包含如下四个模块

request模拟发送HTTP请求。

request模块提供了基本的构造HTTP请求的方法,同时它还可以处理授权验证(authentication)、重定向(redirection)、Cookie会话及其他内容。

urlopen()函数

urlopen()函数可以构造基本的HTTP请求,其函数原型如下:

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

  1. url   请求的URL。可以是一个表示URL的字符串,也可以是一个Request类型的对象。这是必传参数,其他都是可选参数。
  2. data   请求体信息(如在线翻译,在线答题等提交的内容)。data默认值是None,表示以GET方式发送请求;当用户给出data参数时,表示以POST方式发送请求。
  3. timeout   设置网站的访问超时时间,单位为秒。如果请求超出了设置的时间而没有得到响应,就会抛出异常。如果不指定该参数,就会使用全局默认时间
  4. cafile,capath,cadefault        用于实现可信任CA证书的HTTP请求,基本很少使用。
  5. context        实现SSL加密传输,基本很少使用。

调用函数后,返回一个HTTPResponse类型的对象

方法和属性说  明
getcode()/status获取响应状态码
get_url()获取请求的URL
getheaders()获取响应头信息,返回二元组列表
getheader(name)获取特定响应头信息
info()获取响应头信息,返回字符串
read()/readline()读取响应体

 参考代码‘有道翻译’

import urllib.request					#导入request模块
url = 'http://fanyi.youdao.com/translate?smartresult=dict&' \
      'smartresult=rule'				#定义url字符串
datavalue = {
    'i': '苹果',
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '15924715113269',
    'sign': '5c3a992ac57ed879b7678ff05bb3ec44',
    'ts': '1592471511326',
    'bv': 'c74c03c52496795b65595fdc27140f0f',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}												#定义datavalue参数
#编码datavalue参数
datavalue = urllib.parse.urlencode(datavalue).encode('utf-8')
#构造HTTP请求,并将返回的结果赋值给response
response = urllib.request.urlopen(url, data=datavalue)
resp = response.read().decode('utf-8')	#读取网页内容并解码
print(resp)							#输出网页内容

Request()函数 

当HTTP请求信息较复杂时,可用Request()函数进行设置,其函数原型如下: 

Request(url,data=None,headers={},origin_req_host=None, unverifiable=False, method=None)

  1. url:请求的URL。
  2. data:请求体信息,其使用方法与urlopen()函数中的data参数相同。
  3. headers:请求头信息,如User_Agent、Cookie和Host等,是字典类型。
  4. origin_req_host:客户端的host名称或者IP地址。
  5. unverifiable:表示这个请求是无法验证的,在默认情况下设置为False。
  6. method:请求方法,如GET、POST等,是字符串类型。                                                                                                                                                                                         调用函数后,返回一个Request类型的对象,然后再通过urlopen()函数构造完整的HTTP请求。 当服务器有反爬虫机制时,可通过设置headers参数伪装成浏览器去访问网站。

 参考代码‘有道翻译’

import urllib.request						#导入request模块
url = 'http://fanyi.youdao.com/'			            #定义url字符串
#设置headersvalue参数,伪装成浏览器
headersvalue = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; '
                              'Win64; x64) AppleWebKit/537.36 '
                              '(KHTML, like Gecko) Chrome/'
                              '83.0.4103.97 Safari/537.36'}
#创建Request对象,并将返回的结果赋值给request
request = urllib.request.Request(url, headers=headersvalue)
#构造HTTP请求,并将返回的结果赋值给response
response = urllib.request.urlopen(request)
resp = response.read().decode('utf-8')	#读取网页内容并解码
print(resp)							#输出网页内容

 

error处理HTTP请求错误时的异常。

error模块提供了request模块产生的异常处理方法,它主要包含了URLError和HTTPError两个类。

URLError类

是error异常模块的基类,可以捕获request模块产生的异常,它具有一个reason属性(返回异常的原因)。

HTTPError类

是URLError类的子类,专门处理HTTP请求的异常,它具有3个属性,分别为reason(返回异常原因)、code(返回HTTP状态码)和headers(返回请求头)。

因为HTTPError是URLError的子类,并不能处理父类支持的异常处理,所以一般对两种异常分开捕获,可先捕获子类的异常,再捕获父类的异常。

参考代码

 import urllib.request					#导入request模块
import urllib.error					#导入error模块
try: 						            #处理异常
    #构造HTTP请求,并将返回的结果赋值给response
	response=urllib.request.urlopen('http://fanyi.youdao.com/api.htm')
except urllib.error.HTTPError as e:	                       #捕获HTTP请求的异常
	#输出HTTP请求的异常原因、状态码和请求头
    print('异常原因:', e.reason)
    print('状态码:', e.code)
    print('请求头:\n', e.headers)
except urllib.error.URLError as e: 	                        #捕获URL异常
	print(e.reason)					#输出URL异常原因
else:
	#如果没有异常则输出“Request Successfully”
	print('Request Successfully')

 

parse解析、拆分和合并URL。

 parse模块提供了解析URL的方法,包括URL的拆分、合并和转换。

 

参考代码

import urllib.parse					           #导入parse模块
#定义url字符串
url = 'https://f.youdao.com/?path=file&keyfrom=Nav-doc'
print(urllib.parse.urlparse(url))	                                                       #拆分url并输出结果
#合并url并输出结果
print(urllib.parse.urljoin(
    'https://f.youdao.com/','?path=file&keyfrom=Nav-doc'))
#定义params字符串
params = {'path':'file', 'keyfrom':'Nav-doc'} 
#编码params参数,合并url并输出结果
print('https://f.youdao.com/?'+urllib.parse.urlencode(params))
query = 'path=file&keyfrom=Nav-doc'                     	                               #定义query字符串
print(urllib.parse.parse_qs(query))	                                                       #将query字符串转换成字典
print(urllib.parse.parse_qsl(query))	                                                   
#将query字符串转换成列表
keyword = '网络爬虫'					          #定义keyword中文字符串
#将中文字符转换为URL编码,合并后赋值给url
url = 'https://f.youdao.com/?wd='+urllib.parse.quote(keyword)
print(url)						         #输出URL编码的url
#将URL编码转换为中文字符并输出结果
print(urllib.parse.unquote(url))

robotparser解析网站的robots.txt文件。

robotparser模块提供了分析网站Robots协议的RobotFileParser类,它可以通过分析网站的robots.txt文件来判断某网页是否能被爬取。RobotFileParser类提供了多种方法,常用的方法如下。

set_url():设置robots.txt文件的URL。

read():读取robots.txt文件并进行分析。

can_fetch():第一个参数为User_Agent,第二个参数为要爬取网页的URL,判断该网页是否能被爬取。

parse():解析robots.txt文件中某些行的内容。

mtime():返回上次抓取和分析robots.txt文件的时间。

modified():将当前时间设置为上次抓取和分析robots.txt文件的时间。

参考代码

 import urllib.robotparser			#导入robotparser模块
#创建RobotFileParser类对象rp
rp = urllib.robotparser.RobotFileParser()
#设置robots.txt文件的URL
rp.set_url('http://fanyi.youdao.com/robots.txt')
rp.read()					#读取robots.txt文件并进行分析
user_agent = 'Baiduspider'			#定义爬虫名称
#定义有道网页翻译的url
url = 'http://fanyi.youdao.com/web2/index.html'
#判断是否可以爬取有道网页翻译并输出判断结果
print(rp.can_fetch(user_agent, url))
#定义有道人工翻译网页的url
url = 'https://f.youdao.com/?path=fast&keyfrom=Nav-fast'
#判断是否可以爬取有道人工翻译网页并输出判断结果
print(rp.can_fetch(user_agent, url))

3  requests库

requests库可以实现很多功能,包括URL获取、HTTP长连接和连接缓存、HTTP会话、浏览器式的SSL验证、身份认证、Cookie会话、文件分块上传、流下载、HTTP(S)代理功能、连接超时处理等。

import requests						#导入requests模块
#发送HTTP请求,并将返回结果赋值给r
r = requests.get('https://www.douban.com/')
print('响应类型:', type(r)) 				            #输出响应类型
print('请求的URL:', r.url)				            #输出请求的URL
print('响应状态码:', r.status_code)		                        #输出响应状态码
print('请求头:', r.request.headers)		                        #输出请求头

requests库不是Python内置的标准库,使用之前需要安装。

 PyCharm中安装requests库_技术人小柒的博客-CSDN博客_pycharm安装requests库

          请求方法

                GET方法

                GET方法通过get()函数实现,其函数原型如下:

                get(url,params=None,**kwargs)

                (1)url:请求的URL。这是必传参数,其他都是可选参数。

                (2)params:字典或字节序列,作为参数增加到url中。

                (3)**kwargs:控制访问的参数,如headers、cookies、timeout和proxies等。 

 调用函数后,返回一个Response类型的对象

 

                 POST方法

                POST方法通过post()函数实现,其函数原型如下:

        post(url,data=None,json=None,**kwargs)

        (1)url:请求的URL。这是必传参数,其他都是可选参数。

        (2)data:字典、字节序列或文件对象,作为请求体的内容。

        (3)json:JSON格式的数据,作为请求体的内容。

        (4)**kwargs:控制访问的参数,如params、headers、cookies、timeout和proxies等。

        post()函数同样返回一个Response类型的对象。

参考代码 

import requests			                         	#导入requests模块
datavalue = {'name': '11111',
        'password': '222222',
        'remember': 'false'
}								#定义datavalue参数
#定义url字符串
url = 'https://accounts.douban.com/j/mobile/login/basic'
#发送HTTP请求,并将返回结果赋值给r
r = requests.post(url, data=datavalue)
print(type(r)) 				                                   #输出返回对象类型
print(r.url)					                       #输出请求的URL
print(r.status_code)		                                               #输出返回状态码
print(r.request.headers)	                                               #输出请求头

         传递URL参数

         有时网站会通过URL来传递查询参数,这时可使用get()函数或post()函数的params参数进行设置

参考代码 

 import requests					#导入requests模块
paramsvalue = {'q': 'Python'}	                                     #定义字典形式的paramsvalue参数值
#将paramsvalue作为参数增加到url中并发送请求,将返回结果赋值给r
r=requests.get('https://www.douban.com/search',params=paramsvalue)
print(r.url)						#输出url

          定制请求头

        在requests库中,get()或post()函数可以直接传递字典形式的User_Agent信息给headers参数实现定制请求头

        参考代码 

import requests				#导入requests模块
url = 'https://www.douban.com/'	            #定义url字符串
headersvalue = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
}						#设置请求头的User-Agent信息
#不设置headers,发送HTTP请求,并将返回结果赋值给r
r = requests.get(url)
print(r.status_code)				#输出返回状态
print(r.request.headers)			#输出请求头
#设置headers,发送HTTP请求,并将返回结果赋值给r
r = requests.get(url, headers=headersvalue)
print(r.status_code)				#输出返回状态
print(r.request.headers)			#输出请求头

        获取二进制文件 

  图片、音频、视频等文件本质上是由二进制码组成的,有特定的保存格式和对应的解码方式,想要爬取这些文件,需要获取它们的二进制数据。

参考代码

 import requests					#导入requests模块
r=requests.get('https://img9.doubanio.com/view/subject/s/public/s33643895.jpg')					                                                 #发送HTTP请求,并将返回结果赋值给r
#print(r.content) 				            #输出二进制类型返回内容
#print(r.text) 					            #输出文本类型返回内容
#保存二进制类型返回内容为jpg文件
with open('fengmian.jpg', 'wb') as f:
    f.write(r.content)

4  字符编码

在Python 3中,字符串使用str或bytes类型。str类型默认为Unicode编码格式,该编码格式不适合用来传输和存储,所以需要将str类型进行编码,转换成bytes类型(如UTF-8、GBK等格式)。

在做编码转换时,通常需要以Unicode作为中间编码,即先将其他编码的字符串解码(decode()方法)成Unicode,再从Unicode编码(encode()方法)成另一种编码。

如果要查看具体的编码类型,可以使用chardet模块中的detect()方法。

 使用encode()方法和decode()方法实现Unicode和UTF-8之间的编码和解码,输出数据类型、编码和解码结果。

 import chardet				#导入chardet模块
str2byte = '网络爬虫'.encode('utf-8')		#UTF-8编码
print(str2byte) 					#输出编码字符串
print(type(str2byte)) 				#输出编码字符串类型
print(chardet.detect(str2byte)) 		#检测编码类型
byte2str = str2byte.decode('utf-8') 		#解码
print(byte2str) 					#输出解码字符串
print(type(byte2str))				#输出解码字符串类型

 

 在使用Python编写爬虫程序时,大多数网页的编码方式都是UTF-8,requests会自动对来自服务器的内容进行解码。但是有一些网页采用的是GBK等其他编码方式,或者使用gzip进行了压缩,返回的内容中包含的中文会出现乱码的情况。 因此,在解析网页之前,需要检查请求返回内容的编码方式,并进行解码,获取正确的网页内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值