根据使用场景,网络爬虫可分为 通用爬虫 和 聚焦爬虫 两种.
通用网络爬虫 是 捜索引擎抓取系统(Baidu、Google、Yahoo等)的重要组成部分。主要目的是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份
聚焦爬虫,是"面向特定主题需求"的一种网络爬虫程序,它与通用搜索引擎爬虫的区别在于: 聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息。
HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法。
HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)简单讲是HTTP的安全版,在HTTP下加入SSL层。
HTTP
的端口号为80
HTTPS
的端口号为443
络爬虫抓取过程可以理解为模拟浏览器操作的过程
。
浏览器的主要功能是向服务器发出请求,在浏览器窗口中展示您选择的网络资源,HTTP是一套计算机通过网络进行通信的规则。HTTP通信由两部分组成: 客户端请求消息 与 服务器响应消息
URL只是标识资源的位置,而HTTP是用来提交和获取资源。客户端发送一个HTTP请求到服务器的请求消息,包括以下格式:
请求行
、请求头部
、空行
、请求数据
Host (主机和端口号)
Connection (链接类型)
Upgrade-Insecure-Requests (升级为HTTPS请求)
User-Agent (浏览器名称)
Accept (传输文件类型)
Referer (页面跳转处)
Accept-Encoding(文件编解码格式)
Accept-Language(语言种类)
Accept-Charset(字符编码)
Cookie (Cookie)
Content-Type (POST数据类型)
HTTP响应也由四个部分组成,分别是: 状态行
、消息报头
、空行
、响应正文
Cache-Control:must-revalidate, no-cache, private。
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html;charset=UTF-8
Date:Sun, 21 Sep 2016 06:18:21 GMT
Expires:Sun, 1 Jan 2000 01:00:00 GMT
Pragma:no-cache
Server:Tengine/1.4.6
Transfer-Encoding:chunked
Vary: Accept-Encoding
响应状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。
100~199
:表示服务器成功接收部分请求,要求客户端继续提交其余请求才能完成整个处理过程。
200~299
:表示服务器成功接收请求并已完成整个处理过程。常用200(OK 请求成功)。
300~399
:为完成请求,客户需进一步细化请求。例如:请求的资源已经移动一个新地址、常用302(所请求的页面已经临时转移至新的url)、307和304(使用缓存资源)。400~499
:客户端的请求有错误,常用404(服务器无法找到被请求的页面)、403(服务器拒绝访问,权限不够)。500~599
:服务器端出现错误,常用500(请求未完成。服务器遇到不可预知的情况)。服务器和客户端的交互仅限于请求/响应过程,结束之后便断开,在下一次请求时,服务器会认为新的客户端。
为了维护他们之间的链接,让服务器知道这是前一个用户发送的请求,必须在一个地方保存客户端的信息。
Cookie:通过在 客户端 记录的信息确定用户的身份。
Session:通过在 服务器端 记录的信息确定用户的身份。
在Python 3以后的版本中,urllib2这个模块已经不单独存在(也就是说当你import urllib2时,系统提示你没这个模块),urllib2被合并到了urllib中,叫做urllib.request 和 urllib.error 。
例:
urllib2.urlopen()变成了urllib.request.urlopen()
urllib2.Request()变成了urllib.request.Request()
urllib整个模块分为urllib.request, urllib.parse, urllib.error,urllib.robotparser。
urllib.request打开和浏览url中内容
urllib.error包含从 urllib.request发生的错误或异常
urllib.parse解析url
urllib.robotparser解析 robots.txt文件
在python3.X以上版本通过如下命令安装。
pip install urllib3
向指定的url发送请求,并返回服务器响应的类文件对象;支持一系列类文件读取方法,如:read()。其参数时url地址。
urllib.request.Request()
创建request对象,在需要执行更复杂的操作,比如增加HTTP报头,必须创建一个 Request 实例来作为urlopen()的参数;而需要访问的url地址则作为 Request 实例的参数。
给一个网站发送请求的话,通常会比较唐突很容易被拒绝,因此需要使用一个合法的身份进行访问,此时就涉及到代理身份,这就是所谓user-agent头,也可以理解为给我们的爬虫加上一个伪装的身份。
ua_header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
import urllib.request
url = "http://www.itcase.com"
ua_header = {"User-Agent":"Mozilla/5.0 (compatible;MSIE 9.0;Windows NT 6.1;\
Trident/5.0;"}
request = urllib.request.Request(url, headers=ua_header)
response = urllib.request.urlopen(request)
html = response.read()
print(html)
在 HTTP Request 中加入特定的 Header,来构造一个完整的HTTP请求消息。
import urllib.request
url = "http://www.itcase.com"
ua_header = {"User-Agent":"Mozilla/5.0 (compatible;MSIE 9.0;Windows NT 6.1;\
Trident/5.0;"}
request = urllib.request.Request(url, headers=ua_header)
#添加/修改一个特定的header
request.add_header("Connection", "keep-alive")
#查看已有的header
#request.get_header(header_name="Connection")
response = urllib.request.urlopen(request)
#查看响应码状态
print(response.code)
html = response.read()
print(html)
import urllib.request
import random
url = "http://www.itcase.cn"
ua_list = [
"Mozilla/5.0 (Windows NT 6.1;) Apple...",
"Mozilla/5.0 (X11;CrOS i686 2268.111.0...",
"Mozilla/5.0 (Macintosh; U; PPC Mac OS X...",
"Mozilla/5.0 (Macintosh; Intel Mac OS..."
]
#ua_header = {"User-Agent":"Mozilla/5.0 (compatible;MSIE 9.0;Windows NT 6.1;\
# Trident/5.0;"}
user_agent = random.choice(ua_list)
print(user_agent)
request = urllib.request.Request(url)
#添加/修改一个特定的header
request.add_header("User_agent", user_agent)
#查看已有的header
print(request.get_header("User_agent"))
response = urllib.request.urlopen(request)
#查看响应码状态
#print(response.code)
html = response.read()
print(html)
注意:User_agent中U需要大写。
GET
和POST
方法在python3.X中,urllib.parse替代urllib2中的urllib。urllib.parse仅接受URL,不能创建设置了header的Request实例。但其提供的urllib.parse.urlencode()方法可以get查询字符串的产生,编码工作可以将key:value这样的键值对转换成“key=value”这样的字符串;相反urllib.parse.unquote(),把URL编码字符串转换会原先的字符串
import urllib.parse
word = {"wd":"人工智能"}
encode = urllib.parse.urlencode(word)
print(encode)
print(urllib.parse.unquote(encode))
wd=%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD
wd=人工智能
通常HTTP请求提交数据,需要编码成 URL编码格式,然后做为url的一部分,或者作为参数传到Request对象中。
一般用于我们向服务器获取数据,比如说,我们用百度搜索“人工智能”:https://www.baidu.com/s?wd=人工智能
其实是以https://www.baidu.com/s?wd=%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD发送请求的,基于这种方式,我们可以使用Get方式来发送请求。
import urllib.parse
import urllib.request
url = "http://www.baidu.com/s"
word = {"wd":"人工智能"}
word = urllib.parse.urlencode(word)
newrul = 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(newrul, headers=headers)
response = urllib.request.urlopen(request)
print(response.read())
Request请求对象的里有data参数,它就是用在POST里的,我们要传送的数据就是这个参数data,data是一个字典,里面要匹配键值对。
import urllib.parse
import urllib.request
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
headers = {"User-Agent":"Mozilla..."}
formdata = {"type":"AUTO","i":"i love python","doctype":"json","xmlVersion":"1.8","keyfrom":"fanyi.web","ue":"UTF-8","action":"FY_BY_ENTER","typoResult":"true"}
data = urllib.parse.urlencode(formdata)
request = urllib.request.Request(url, data=data, headers=headers)
response = urllib.request.urlopen(request)
print(response.read())
有些网页内容使用AJAX加载,只要记得,AJAX一般返回的是JSON,直接对AJAX地址进行post或get,就返回JSON数据了。
import urllib.parse
import urllib.request
# demo1
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action"
headers={"User-Agent": "Mozilla...."}
# 变动的是这两个参数,从start开始往后显示limit个
formdata = {'start':'0','limit':'10'}
data = 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"))
某些https协议的网站需要进行验证SSL证书,如果SSL验证不通过或操作系统不信任服务器的安全证书,则无法访问,urllib可以为HTTPS请求验证SSL证书。如果以后遇到这种网站,我们需要单独处理SSL证书,让程序忽略SSL证书验证错误,即可正常访问。
import urllib.request
import urllib.parse
import ssl
context = ssl._create_unverified_context()
url = "https://www.12306.cn/mormhweb/"
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
request = urllib.request.Request(url, headers=headers)
reponse = urllib.request.urlopen(request, context=context)
print(reponse.read())
注:urllib目前在python3.x的版本中貌似已经不用ssl也可以爬取数据。
是数字证书认证中心的简称,是指发放、管理、废除数字证书的受信任的第三方机构。CA的作用是检查证书持有者身份的合法性,并签发证书,以防证书被伪造或篡改,以及对证书和密钥进行管理。可以看做网络中的身份证。
在上文中用到的urlopen其实就是一个Opener,是系统预定义的一个OpenerDirector实例。但是urlopen()不支持代理、cookie等高级功能,因此我们还需要自己创建一个Opener来承载更强大的功能。构建步骤如下代码:
import urllib.request
#构建HTTPHandler处理器
http_handler = urllib.request.HTTPHandler()
#创建支持处理http请求的opener对象
opener = urllib.request.build_opener(http_handler)
#构建request请求
request = urllib.request.Request("http://baidu.com/")
#调用自定义的opner的open方法,发送request请求
response = opener.open(request)
#获取服务器响应内容
print(response.read())
上述代码实现的功能和urlopen作用一样,为了说明自定义的opener的妙用,我们只举个简单例子:查看Debug log
http_handler = urllib.request.HTTPHandler(debuglevel=1)
想必大家都听说反爬虫这个概念,对付这个问题最好用的方式就是使用代理IP。原理就是每隔一段时间更换一个代理,这样即使IP被禁用了也可以换个IP继续爬取。在urllib中通过ProxyHandler来设置使用代理服务器。使用方法见下列代码
import urllib.request
httpproxy_handler = urllib.request.ProxyHandler({"http":"124.88.67.81.80"})
nullproxy_handler = urllib.request.ProxyHandler({})
#验证有无代理的区别而设置的开关
proxySwitch = True
#使用代理handler对象
if proxySwitch:
opener = urllib.request.build_opener(httpproxy_handler)
else:
opener = urllib.request.build_opener(nullproxy_handler)
request = urllib.request.Request("http://baidu.com/")
response = opener.open(request)
print(response.read())
主要用途有如下两种:
作用是验证代理授权的用户名和密码,防止407错误,构造方法如下代码。
import urllib.request
import urllib.parse
user = "mr_mao_hacker"
passwd = "sffqry9r"
proxyserver = "61.158.163.130:16816"
#构建密码管理对象,保存需要处理的用户名和密码
passwdmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
#添加账户信息,add_password中的参数分别是:realm与远程服务器相关的域,常为NONE
#代理服务器,用户名,密码
passwdmgr.add_password(None, proxyserver, user, passwd)
#构建ProxyBasicAuthHandler对象
proxyauth_handler = urllib.request.ProxyBasicAuthHandler(passwdmgr)
#通过build_opener()使用Handler对象
opener = urllib.request.build_opener(proxyauth_handler)
request = urllib.request.Request("http://www.baidu.com/")
response = opener.open(request)
print(response.read())
防止在web服务器需要身份验证时,发生401错误。
import urllib.request
import urllib.parse
user = "test"
passwd = "124"
webserver = "http://192.168.199.107"
passwdmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
passwdmgr.add_password(None, webserver, user, passwd)
#构建HTTP基础用户名/密码验证的HTTPBasicAuthHandler
httpauth_handler = urllib.request.HTTPBasicAuthHandler(passwdmgr)
opener = urllib.request.build_opener(httpauth_handler)
request = urllib.request.Request("http://192.168.199.107")
response = opener.open(request)
print(response.read())
网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。由于HTTP是无状态的面向连接的协议, 为了保持连接状态, 引入了Cookie机制。
Cookie是http消息头中的一种属性,包括:
Cookie名字(Name)
Cookie的值(Value)
Cookie的过期时间(Expires/Max-Age)
Cookie作用路径(Path)
Cookie所在域名(Domain)
Cookie安全连接(Secure)
在写爬虫中cookie的重要作用是判断注册用户是否已经登录网址,此时在网页上用户会看到是否保存用户信息的提示。获取一个有登录信息的Cookie模拟登录代码如下:
cookielib:主要作用是创建存储cookie的对象,常用的对象有:CookieJar(最为常用)、FileCookieJar(检索cookie信息并将cookie存储到文件中)、MozillaCookieJar(创建与Mozilla浏览器 cookies.txt兼容
)、LWPCookieJar (创建与libwww-perl标准的 Set-Cookie3 文件格式
兼容),通常如果和本地文件交互会使用MozillaCookieJar或LWPCookieJar。
HTTPCookieProcessor:主要作用是处理cookie对象,并构建handler对象。
import urllib.request
from http import cookiejar
cookiejar = cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookiejar)
opener = urllib.request.build_opener(handler)
opener.open("http://www.baidu.com/")
cookieStr = ""
for item in cookiejar:
cookieStr = cookieStr + item.name + "=" +item.value + ";"
print(cookieStr[:-1])
import urllib.request
from http import cookiejar
filename = "cookie.txt"
cookiejar = cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookiejar)
opener = urllib.request.build_opener(handler)
response = opener.open("http://www.baidu.com/")
cookiejar.save()
import urllib.request
from http import cookiejar
cookiejar = cookiejar.MozillaCookieJar()
cookiejar.load('cookie.txt')
handler = urllib.request.HTTPCookieProcessor(cookiejar)
opener = urllib.request.build_opener(handler)
response = opener.open("http://www.baidu.com/")
参考:
https://blog.csdn.net/zd147896325/article/details/78957901