1.入门程序
爬虫采集数据,主要采集网站数据,通常情况下操作步骤如下:
1)确定目标网站url地址
2)对目标url地址发送请求
3)获取网站返回的响应数据‘
4)对响应数据进行解析处理
5)得到目标数据
具体代码如下
# -*- coding: utf-8 -*-
# 引入爬虫程序依赖的模块
from urllib import request
# 定义要采集数据的目标地址
target_url = "http://www.sina.com"
# 向服务器发送请求,获取服务器的响应数据
response = request.urlopen(target_url)
# 展示获取到的数据
html = response.read()
print(html.decode("utf-8"))
2.数据编码处理
我们通过爬虫程序可以得到网站返回的数据,但是返回的数据在展示的过程中,出现了乱码,这是因为网站本身有自己的字符编码,而我们的程序在数据采集完成后在控制台展示的过程中使用的是本地默认的编码,由于编码的不一致,导致了乱码的产生。
网页中的编码一般会定义在<meta charset=''>标签中。所以爬虫采集网页数据是可以分为两个步骤进行操作,先采集批量网页中的一个网页查看编码格式,然后在代码中使用指定的格式进行解码,得到正确的数据后,再进行批量网页数据的采集,这就是手工指定编码方式
3.使用urllib
3.1 url概述
urllib库是python内置的HTTP请求库,不需要额外安装即可使用。它包含四个模块:
1)request: 它是最基本的HTTP请求模块,可以用来模拟发送请求,只需要给库方法传入url以及额外的参数,就可以模拟实现浏览器输入网址敲回车的过程了
2)error: 异常处理模块,如果请求出现错误,我们可以捕获这些异常,进行重试或其他操作保证进程不会终止
3)parse: 一个工具模块,提供了许多url方法,比如拆分、解析、合并等
4)robotparser: 主要用来识别网站的tobots.txt文件,判断网站是够可爬,使用较少
3.2发送请求
使用urllib的request模块,可以实现发送请求并返回响应
3.2.1ulopen()
urllib.request模块提供了最基本的构造HTTP请求方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理授权验证、重定向、浏览器cookies以及其他内容
import urllib.request
response= urllib.request.urlopen( ' https://www.python.org')
pri 1t(response. read(). decode (’ utf-8'))
传参:
1)data参数
data参数是可选的,如果需添加该参数且是bytes类型,则需通过bytes()方法转化。若传递此参数,则其请求方式由GET请求变为POST请求
import urllib.parse
import urllib.request
data = bytes(urllib . parse . urlencode({'word ’:’ hello'}), encoding =’ ut 8')
response= urllib.request.urlopen('http://httpbin.org/post ’, data=data)
print(response.read())
次数传递参数为Word,值为hello。需被转化为bytes类型,需要用 urllib.parse
块里的 urlencode ()方法来将参数字典转化为字符串;第 个参数指定编码格式,这里指定为 utf8,这里请求的站点是 httpbin .org ,它可以提供 HTTP 请求测试 本次我们请求的 URL http :// httpbin.org/ post ,这个链接可以用来测试 POST 请求,它可以输出请求的一些信息 ,其中包含我们传递的 data参数。运行结果如下
{
"args" : {},
”data ”:,
"files”. {}, ”form”:
{ “word ":”hello”
},
"headers " {
“ Accept-Encoding ":”identity”,
“ Content-Length”: '’ 10”,
”Content ype ":"application/x-www-form-urlencoded",
"Host ”:” httpb n.org ”,
”User-Agent"”Python-urllib/3. 5"
’' j son ”: null ,
”origin '’,” 123.124.23.253 ”,
"url”:”http://httpbin.org/post"
}
传递的参数出现在了from字段中,表名模拟了表单的提交方式,以post请求传递数据
2)timeout参数
timeout参数用于设置超时时间,单位为秒。若请求超出了设置的这个时间还没有得到响应,则会抛出异常,若不指定该参数,就会使用全局默认时间,它支持HTTP、HTTPS、FTP请求。可以通过设置这个超时时间来控制一个网页,若长时间未响应,则跳过其抓取
3)其他参数
除了 data 参数和 timeout 参数外,还有 context 参数,它必须是 ssl.SSLContext 类型,用来指定SSL。此外, cafile ca path 这两个参数分别指定 CA 证书和它的路径,这个在请求 HTTPS 链接时有用,cadefault 参数现在已经弃用了,其默认值为 False
3.2.2 request
利用urlopen()方法可以实现最基本请求的发起,但这几个简单的参数并不足以构造一个请求。如果请求中需要加入headers等信息,则需要用更加强大的request请求进行构建。request用法如下:
import urllib .request
request = urllib.request.Request(’ https://python .org')
response = urllib .request.urlopen(request)
print(response.read().decode (’ utf-8'))
此处依然用urlopen()方法发送请求,但参数却由url变为request类型的对象,通过构造这个数据结构,一方面可以将请求独立成一个对象,另一个方面可以更加灵活地配置参数。request参数构造方法如下:
class urllib. request. Request ( ur 1, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
齐总第一个参数url用于请求URL,为必填参数,其他都是可选参数
第二个参数data如果要传,必须要传types类型的,若它是字典,可先用urllib.parse模块中的urlencode()编码
第三个参数headers是一个字典,它就是请求头,我们可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add_header()方法添加
第四个参数orgin_req_host指的是请求方的host或IP地址
第五个参数unverifiable表示这个请求是否无法验证的,默认是false,表示用户没有足够权限来接收这个请求
第六个参数method是一个字符串,用来指示请求的使用方法
3.2.3 高级用法
在上面的过程中,我们虽然可以构造请求,但对于更加高级的一些操作无法实现,此时就需要handler大展雄姿了。我们可以把handler理解为各种处理器,有专门验证登录的,有处理cookies的,有处理代理设置的,利用它们,我们几乎可以做到HTTP请求中的所有事情。
首先,介绍一下urllib.request模块中的basehandler类,它是所有其他handler的父类,提供了最基本的方法。另外一个比较重要的类就是openerdirector,我们可以成为opener,之前用过的urlopen()方法,实际上就是urllib为我们提供的额一个opener。之所以引入opener,是因为需要实现更加高级的功能。之前使用的request和urlopen()相当于类库为你封装好了及其常用的请求方法,利用它们可以完成基本的请求。但现在需要实现更加高级的功能,所以需要深入一层进行配置,使用能更加底层的实例来完成操作,所以这里用到了opener。
opener可以使用open()方法,返回的类型和urlopen()如出一辙,它与handler的关系简而言之就是利用handler来构建opener
1)代理
在做爬虫时,可能会由于短时间内造成服务器压力而被认定为恶意攻击从而导致IP地址封禁,从而导致IP地址不可用。为了避免此类情况的发生,我们可以使用代理。添加代理方法如下:
from urllib.error import URLError
from urllib.request import ProxyHandler, build opener
proxy _handler = ProxyHandler({
’ http ':’http://127.o.o .1:9743 ’,
’ https’:’https://127.0 .0.1:9743 ’
})
opener = build_opener(proxy_handler)
try:
response = opener.open (’ https://www.baidu.com')
print(response.read() .decode (’ utf-8'))
except URLError as e:
print(e .reason)
2)cookies
cookies的处理需要相关的handler,将网站cookies获取下来的代码如下:
import http .cookiejar, urllib.request
cookie = http. cookie jar. CookieJar()
handler = urllib .request.HTTPCookieProcessor (cookie)
opener = urllib.request . build opener(handler )
response = opener. open (’ http://www.baidu.com')
or item in cookie:
print(item.name+”=”+item.value)
4.处理异常
异常可能会导致程序因报错而终止,因此异常的处理是十分必要的。urllib的error模块定义了由request模块产生的异常,若果出现了问题,request模块便会跑出error模块定义的异常
4.1 urlerror
1)urlerror类来自urllib库的error模块,它继承自oserroe类,是error异常模块的基类,由request模块产生的异常都可以通过这个类来进行捕获
2)HTTPerror
它是URLerror的子类,专门用来处理HTTP请求错误,比如认证请求失败等等。它有如下三个属性:
code :返回HTTP状态码
reason:同父类一样用于返回错误的原因
headers:返回请求头
4.2 解析链接
1)urlparse()
该方法可以实现URL的识别和分段。一个标准的url都会符合规则,利用urlparse()方法将其拆分下来,即:
解析时有特定的分隔符
比如,://前面的就是 scheme ,代表协议;第一个/符号前面便是 netloc ,即域名,后面是 path ,即访
问路径;分号;前面是 pa rams ,代表参数;问号?后面是查询条件 query 般用作 GET 类型的 URL;
井号#后面是锚点,用于直接定位页面内部的下拉位置
它有三个参数:
urlstring:这是必填项,即待解析的URL
scheme:它是默认的协议,加入这个链接没有带协议信息,会将这个作为默认的协议
allow_fragments:即是否忽略fragment,如果它被设置为false.fragment部分就会被忽略,它会被解析为path、parametes或者query的一部分,而fragment部分为空
2)urlunparse()
有了urlparse(),相应的就有了它的队里方法urlunparse。它接收的参数是一个可迭代对象,但长度必须为6,否则会抛出参数数量不足或过多的问题
3)urlsplit()
这个方法和urlparse()方法非常相似,只不过它不再单独解析params这一部分,只返回五个结果。
4) urlunsplit()
urlunparse ()类似,它也是将链接各个部分组合成完整链接的方法,传人的参数也是一个可迭代对象,例如列表 元组等,唯 的区别是长度必须为5
5)urljoin()
有了 urlunparse ()和 urlu isplit ()方法,我们可以完成链接的合井,不过前提必须要有特定长度的对象,链接的每一部分都要清晰分开。此外,生成链接还有另 个方法,那就是 urljoin ()方法 我们可以提供一个 base_url (基础链接)作为第1 个参数,将新的链接作为第二个参数,该方法会分析 base_url 的scheme、 netloc和 path这3个内容并对新链接缺失的部分进行补充,最后返回结果
6) urlencode()
这个方法非常常用有时为了更加方便的构造参数,我们会事先用字典来表示,要转化为url的参数时,只需要调用该方法即可
7) parse_qs()
有了序列化,必然就有反序列化 如果我们有一串 GET 请求参数,利用 parse qs ()方法, 就可以将它转回字典
8)parse_qsl()
另外,还有 parse_qs ()方法,它用于将参数转化为元组组成的列表
9)quote()
该方法可以将内容转化为 URL 编码的格式 URL 中带有中文参数时,有时可能会导致乱码的问题,此时用这个方法可以将巾文字符转化为 RL 编码
10)unquote()
有了 quote ()方法,当然还有 unquote ()方法,它可以进行 URL 解码
5.分析robots协议
利用 urllib的 robot parser 模块,我们可以实现网站 Ro 协议的分析
1)robots协议
Robots 协议也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准( Robots ExclusionProtocol ),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取 它通常是一个叫作 ro bots .txt的文本文件,一般放在网站的根目录下。当搜索’爬虫访问一个站点时,它首先会检查这个站点根目录下是否存在 ro ots.txt 文件,如果存在,搜索爬虫会根据其中定义的爬取范围来爬取 如果没有找到这个文件,搜索爬虫便会访问所有可直接访问的页面
2)robotparser
该模块提供了一个类robotfileparser,
它可以根据某网站的robot.txt文件来判断一个爬去爬虫是否有权限来爬去这个网页,该类使用只需要在构造方法里传入robots.txt的链接即可。常用方法:
set_url():用来设置robots.txt文件的链接,如果在创建robotfileparser对象时传入了链接,那么就不需要再使用该方法设置
read():读取robots.txt文件并进行分析。该方法执行一个读取和分析操作,如果不调用该方法,接下来的判断都会为false,所以一定得调用,这个方法不会反悔任何内容,但是执行了读取操作
3)parse():用来解析robots.txt文件,传入的参数是robots.txt某些行的内容,它会按照robots.txt的语法规则来分析这些内容
4)can_fetch():该方法传入两个参数,第一个是user—agent,第二个是要抓取的url。返回的内容是该搜索引擎是否可以抓取这个url,返回的结果是True或False
5)mtime():返回的是上次抓取和分析robots.txt的时间,这对于长时间分析和抓取的搜索爬虫是很有必要的,可能会需要定期检查来抓取最新的robots.txt
6)modified():它同样对长时间分析和抓取的搜索爬虫很有帮助,将当前时间设置为上次抓取和分析robots.txt的时间