爬虫的基本原理:

学过Python的伙伴都应该知道Python用来写爬虫是件很简单很爽的事情。但是有些小伙伴不了解爬虫到底是什么,会纳闷为什么爬虫要设置什么请求头、请求体等等,到底如何去发送这个请求啊。当然有的小伙伴使用过很多爬虫的请求库,解析库,写过很多爬虫,但是可能他们的思路脉络也不是太清晰。后面会陆续学到其中原理。

什么是爬虫?

爬虫即网络爬虫,英文是Web Spider。翻译过来就是网络上爬行的蜘蛛,如果把互联网看作一张大网,那么爬虫就是在大网上爬来爬去的蜘蛛,碰到想要的食物,就把他抓取出来。

我们在浏览器中输入一个网址,敲击回车,看到网站的页面信息。这就是浏览器请求了网站的服务器,获取到网络资源。那么,爬虫也相当于模拟浏览器发送请求,获得到HTML代码。HTML代码里通常包含了标签和文字信息,我们就从中提取到我们想要的信息。

通常爬虫是从某个网站的某个页面开始,爬取这个页面的内容,找到网页中的其他链接地址,然后从这个地址爬到下一个页面,这样一直不停的爬下去,进去批量的抓取信息。那么,我们可以看出网络爬虫就是一个不停爬取网页抓取信息的程序。

爬虫的基本流程:

1.确定目标数据

2.确定数据来源

3.来源的结构分析

4.实现构思

防爬手段:

请求限制:

1.对用户的来源的User-Agent进行判断

2.对用户的访问频率进行设置

3.IP代理

高级手段:

1.登陆授权

2.验证码

先来试试简单的网站数据爬取实验:

from urllib.request import urlopen
r = urlopen('http://www.baidu.cn/')
# urlopen返回的是一个对象
#print(r)
#获取源代码中的数据
print(r.read().decode())

#decode()默认大解码格式是utf-8,可在该函数里面加上特定的编码格式
#获取响应状态
#print("访问状态码:",r.getcode())
#获取响应的真实的URL
#print(r.geturl())
#获取响应头
#print(r.info())

传参数的编码设置方式:

#https://www.baidu.com/s?wd=三星&ie=utf-8&tn=02049043_8_pg&ch=6
from urllib.request import urlopen
from urllib.parse import quote
#如何处理中文传参乱码的问题from urllib.parse import quote利用该转码工具,仅限传参使用比较合适
kw = quote("三星")
html = "http://www.baidu.com/s?wd="+kw+"&ie=utf-8&tn=02049043_8_pg&ch=6"
r = urlopen(html)
#获取源代码中的数据
print(r.read().decode())

#通过一个Request对象构造一个headers的头部信息进行爬取

from urllib.request import urlopen,Request

html = "http://www.codeseeding.com/portal.php"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"
}
request = Request(html,headers=headers)
r = urlopen(request)
print(r.read().decode())

如何解决中文传参乱码的第二种方法:

from urllib.request import urlopen
from urllib.parse import urlencode
#如何处理中文传参乱码的问题第二种方式
#利用字典的方法,对url中的所有中文都可以编码
args = {
    "keyword":"飞利浦"
}
#print(urlencode(args))打印keyword的字节码
html = "https://search.jd.com/Search?{}".format(urlencode(args))
r = urlopen(html)
#获取源代码中的数据
print(r.read().decode())

爬虫的基本流程

1.发起请求(要注意该请求服从哪些协议):

通过HTTP库向目标站点发起请求,即发送一个Request,请求可以包含额外的headers等信息,然后等待服务器响应。这个请求的过程就像我们打开浏览器,在浏览器地址栏输入网址:www.baidu.com,然后点击回车。这个过程其实就相当于浏览器作为一个浏览的客户端,向服务器端发送了 一次请求。

2.获取响应内容:

如果服务器能正常响应,我们会得到一个ResponseResponse的内容便是所要获取的内容,类型可能有HTMLJson字符串,二进制数据(图片,视频等)等类型。这个过程就是服务器接收客户端的请求,进过解析发送给浏览器的网页HTML文件。

3.解析内容:

得到的内容可能是HTML,可以使用正则表达式,网页解析库进行解析。也可能是Json,可以直接转为Json对象解析。可能是二进制数据,可以做保存或者进一步处理。这一步相当于浏览器把服务器端的文件获取到本地,再进行解释并且展现出来。

4.保存数据:

保存的方式可以是把数据存为文本,也可以把数据保存到数据库,或者保存为特定的jpg,mp4 等格式的文件。这就相当于我们在浏览网页时,下载了网页上的图片或者视频。

Request

1.什么是Request?

浏览器发送信息给该网址所在的服务器,这个过程就叫做HTTP Request

2.Request中包含什么?

  • 请求方式:请求方式的主要类型是GET,POST两种,另外还有HEADPUTDELETE等。
  • GET 请求的请求参数会显示在URL链接的后面,比如我们打开百度,搜索“图片”,我们会看到请求的URL链接为https://www.baidu.com/s?wd=图片
  • 而 POST 请求的请求参数会存放在Request内,并不会出现在 URL 链接的后面,比如我们登录知乎,输入用户名和密码,我们会看到浏览器开发者工具的Network页,Request请求有Form Data的键值对信息,那里就存放了我们的登录信息,有利于保护我们的账户信息安全;
  • 请求 URL:URL 全称是统一资源定位符,也就是我们说的网址。比如一张图片,一个音乐文件,一个网页文档等都可以用唯一URL来确定,它包含的信息指出文件的位置以及浏览器应该怎么去处理它;
  • 请求头(Request Headers):请求头包含请求时的头部信息,如User-Agent(指定浏览器的请求头),HostCookies等信息;
  • 请求体:请求体是请求是额外携带的数据,比如登录表单提交的登录信息数据。
  • (推荐一个比较好用的压缩软件Bandizip,使用Python的解析包的时候这个解压比较好)

Response

1.什么是Response?

服务器收到浏览器发送的信息后,能够根据浏览器发送信息的内容,做出相应的处理,然后把消息回传给浏览器,这个过程就叫做HTTP Response

2.Response中包含什么?

  • 响应状态:有多种响应状态,比如200代表成功,301 跳转页面,404 表示找不到页面,502 表示服务器错误;
  • 响应头(Response Headers):比如内容类型,内容长度,服务器信息,设置Cookie等;
  • 响应体:响应体最主要的部分,包含了请求资源的内容,比如网页 HTML 代码,图片二进制数据等。

简单演示

import requests # 导入requests库,需要安装

# 模拟成浏览器访问的头
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
resp = requests.get('https://www.baidu.com',headers=headers)
print(resp.text) # 打印出网页源代码
print(resp.status_code) # 打印出状态码

运行成功后可以看到打印出来的 html 源代码和 200 状态码了。这就基本上实现了爬虫的RequestResponse的过程。

能抓到

什么样的数据?

  • 网页文本:如 HTML 文档,Ajax加载的Json格式文本等;
  • 图片,视频等:获取到的是二进制文件,保存为图片或视频格式;
  • 其他只要能请求到的,都能获取。

演示:

import requests

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
resp = requests.get('http://www.baidu.com/img/baidu_jgylogo3.gif',headers=headers)
print(resp.content) # 二进制文件使用content
# 保存图片
with open('logo.gif','wb') as f:
    f.write(resp.content)
    print('Ok')

成功运行就可以看到打印出来的图片的二进制数据,可保存成功后打印的 OK,这个时候我们打开文件夹就可以看到下载下来的图片了。这几行代码就简单的演示了爬虫保存文件的过程。

解析方式有哪些?

  • 直接处理,比如简单的页面文档,只要去除一些空格的数据;
  • Json解析,处理Ajax加载的页面;
  • 正则表达式;
  • BeautifulSoup库;
  • PyQuery;
  • XPath。