爬虫(一):爬虫原理与数据抓取

1.通用爬虫和聚焦爬虫

根据使用场景,网络爬虫可分为 通用爬虫 和 聚焦爬虫 两种.

通用爬虫

通用网络爬虫 是 捜索引擎抓取系统(Baidu、Google、Yahoo等)的重要组成部分。主要目的是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份

聚焦爬虫

聚焦爬虫,是"面向特定主题需求"的一种网络爬虫程序,它与通用搜索引擎爬虫的区别在于: 聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓取与需求相关的网页信息。

 

2.HTTP和HTTPS

HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法。

HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)简单讲是HTTP的安全版,在HTTP下加入SSL层。

  • HTTP的端口号为80
  • HTTPS的端口号为443

2.1 HTTP工作原理

络爬虫抓取过程可以理解为模拟浏览器操作的过程

浏览器的主要功能是向服务器发出请求,在浏览器窗口中展示您选择的网络资源,HTTP是一套计算机通过网络进行通信的规则。HTTP通信由两部分组成: 客户端请求消息 与 服务器响应消息

爬虫(一):爬虫原理与数据抓取_第1张图片

 2.2客户端HTTP请求

URL只是标识资源的位置,而HTTP是用来提交和获取资源。客户端发送一个HTTP请求到服务器的请求消息,包括以下格式:

请求行请求头部空行请求数据

爬虫(一):爬虫原理与数据抓取_第2张图片

常用的请求报头

Host (主机和端口号)

Connection (链接类型)

Upgrade-Insecure-Requests (升级为HTTPS请求)

User-Agent (浏览器名称)

Accept (传输文件类型)

Referer (页面跳转处)

 Accept-Encoding(文件编解码格式)

Accept-Language(语言种类)

Accept-Charset(字符编码)

Cookie (Cookie)

Content-Type (POST数据类型)

2.3 服务端HTTP响应

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

2.4 响应状态码

响应状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。

常见状态码:

  • 100~199:表示服务器成功接收部分请求,要求客户端继续提交其余请求才能完成整个处理过程。

  • 200~299:表示服务器成功接收请求并已完成整个处理过程。常用200(OK 请求成功)。

  • 300~399:为完成请求,客户需进一步细化请求。例如:请求的资源已经移动一个新地址、常用302(所请求的页面已经临时转移至新的url)、307和304(使用缓存资源)。
  • 400~499:客户端的请求有错误,常用404(服务器无法找到被请求的页面)、403(服务器拒绝访问,权限不够)。
  • 500~599:服务器端出现错误,常用500(请求未完成。服务器遇到不可预知的情况)。

2.5Cookie 和 Session:

服务器和客户端的交互仅限于请求/响应过程,结束之后便断开,在下一次请求时,服务器会认为新的客户端。

为了维护他们之间的链接,让服务器知道这是前一个用户发送的请求,必须在一个地方保存客户端的信息。

Cookie:通过在 客户端 记录的信息确定用户的身份。

Session:通过在 服务器端 记录的信息确定用户的身份。

3.urllib库的基本使用

在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

3.1urllib.request.urlopen()

向指定的url发送请求,并返回服务器响应的类文件对象;支持一系列类文件读取方法,如:read()。其参数时url地址。

urllib.request.Request()

创建request对象,在需要执行更复杂的操作,比如增加HTTP报头,必须创建一个 Request 实例来作为urlopen()的参数;而需要访问的url地址则作为 Request 实例的参数。

3.2 User-Agent

给一个网站发送请求的话,通常会比较唐突很容易被拒绝,因此需要使用一个合法的身份进行访问,此时就涉及到代理身份,这就是所谓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)

 

 添加更多的Header信息

在 HTTP Request 中加入特定的 Header,来构造一个完整的HTTP请求消息。

  • 通过调用Request的add_header()方法添加/修改一个特定的header;get_header()来查看已有的header
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)
  • 随机添加/修改User-Agent
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需要大写。

4.HTTP/HTTPS的GETPOST方法

在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对象中。 

4.1 Get方式:

一般用于我们向服务器获取数据,比如说,我们用百度搜索“人工智能”: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())

4.2 POST方式:

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())

4.3 获取AJAX加载的内容

有些网页内容使用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"))

4.4 处理HTTPS请求 SSL证书验证

某些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也可以爬取数据。

4.5 CA(Certificate Authority)

是数字证书认证中心的简称,是指发放、管理、废除数字证书的受信任的第三方机构。CA的作用是检查证书持有者身份的合法性,并签发证书,以防证书被伪造或篡改,以及对证书和密钥进行管理。可以看做网络中的身份证。

5.Handler处理器 和 自定义Opener

在上文中用到的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)

5.1 ProxyHandler处理器(添加代理)

想必大家都听说反爬虫这个概念,对付这个问题最好用的方式就是使用代理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())

5.2 密码管理的类:HTTPPasswordMgrWithDefaultRealm()

主要用途有如下两种:

  • 代理授权验证:ProxyBasicAuthHandler()

作用是验证代理授权的用户名和密码,防止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客户端授权验证:HTTPBasicAuthHandler()

防止在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())

6.Cookie

网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。由于HTTP是无状态的面向连接的协议, 为了保持连接状态, 引入了Cookie机制。

Cookie是http消息头中的一种属性,包括:

Cookie名字(Name)
Cookie的值(Value)
Cookie的过期时间(Expires/Max-Age)
Cookie作用路径(Path)
Cookie所在域名(Domain)
Cookie安全连接(Secure)

在写爬虫中cookie的重要作用是判断注册用户是否已经登录网址,此时在网页上用户会看到是否保存用户信息的提示。获取一个有登录信息的Cookie模拟登录代码如下:

6.1 cookielib库 和 HTTPCookieProcessor处理器

cookielib:主要作用是创建存储cookie的对象,常用的对象有:CookieJar(最为常用)、FileCookieJar(检索cookie信息并将cookie存储到文件中)、MozillaCookieJar(创建与Mozilla浏览器 cookies.txt兼容)、LWPCookieJar (创建与libwww-perl标准的 Set-Cookie3 文件格式兼容),通常如果和本地文件交互会使用MozillaCookieJar或LWPCookieJar。

HTTPCookieProcessor:主要作用是处理cookie对象,并构建handler对象。

  • 获取Cookie,并保存到CookieJar()对象中

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])
  • 访问网站获得cookie,并把获得的cookie保存在cookie文件中

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()
  • 从文件中获取cookies,做为请求的一部分去访问

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

你可能感兴趣的:(爬虫)