文章目录
根据使用的场景可以将网络爬虫分为通用爬虫和聚焦爬虫
一. 通用爬虫
1. 定义
从互联网上搜集网页,采集信息,这些网页信息用于为搜索引擎建立索引从而提供支持,它决定着整个引擎系统的内容是否丰富,信息是否及时,因此其性能的优劣直接影响着搜索引擎的效果。
2. 目的
是搜索引擎抓取系统的重要组成部分,主要的目的是将互联网上的网页下载到本地,形成一个互联网的镜像备份。
3. 工作基本流程
先是进行信息采集,然后进行索引与检索,然后通过web接口与人交互
4. 搜索引擎如何获取一个新的网站的URL
(1)新的网站主动向搜索引擎提交网站
(2)在其他网站上设置新的网站外链
(3)和DNS解析服务商(eg:DNSPord)等合作,新的网站域名将迅速抓取
5. 搜索引擎限制
搜索引擎蜘蛛的爬行是被输入一定的规则,它需要遵循一些命令或者文件内容
(1)rel = “ nofollow ”
告诉搜索引擎爬虫无需抓取页面,同时告诉搜索引擎无需将当前页的Pagerank传递到目标页。
(2)Robot 协议(爬虫协议,机器人协议)
全称是“网络爬虫排除标准”(Robots Exclusion Protocol)网站通过Robots协议告诉搜索引擎哪些页面可以抓取。哪些页面不可以抓取。
6. 通用爬虫的局限性
(1) 大多数情况下,页面中的90% 的内容对于用户来说是无用的
(2) 搜索引擎无法提供针对具体某个用户的搜索结果
(3) 图片,数据库,音频,视频等多媒体不能很好的发现和获取
(4)基于关键字的检索,难以支持根据语义信息提出的查询,无法准确的理解用户的具体需求
二. 聚焦爬虫
定义
聚焦爬虫是“面向特定主题需求”的一种网络爬虫程序,它与通用搜索引擎爬虫的区别在于: 聚焦爬虫在实施网页抓取时会对内容进行筛选,尽量保证只抓取与需求相关的网页信息。
(一) HTTP 和 HTTPS
1. HTTP协议——80端口
HyperTextTransferProtocol —— 超文本传输协议是一种发布和接收HTML页面的方法
2. HTTPS ——443端口
HyperTextTransferProtocol —— 通俗说是HTTP 的安全版,在HTTP下加入SSL层
3. HTTP工作原理
网络爬虫的过程可以理解是模拟浏览器操作的过程
客户端向服务端发送一个请求,然后服务端向客户端返回一个响应
浏览器发送请求的过程:
1) 当用户在浏览器的地址栏中输入一个URL 并且按回车键之后,浏览器会向HTTP 服务器发送HTTP请求。HTTP请求主要分为”GET“和“POST”两种。
2) 当我们在浏览器上输入URL (也就是网址)的时候,浏览器会发送一个Request请求去获取该网址的html文件,服务器会把Response文件对象发送回浏览器。
3) 当浏览器分析Response 中的HTML ,发现其中引用了很多文件,比如mages文件,CSS 文件,JS文件。浏览器会自动再次发送请求(Request)去获取图片,CSS文件,JS文件。
4) 当所有的文件都下载成功之后,网页会根据HTML 语法结构,完整的显示出来
4. URL
URL(Uniform ResourceLocator的缩写): 统一资源定位符,是用于完整的描述Internet 上网页和其他资源的地址的一种标识方法/
基本的格式:
scheme://host[:port#]/path/…/[?query-string][#anchor]
其中:
- query-string: 参数,发送给http服务器的数据
- anchor: 锚 (跳转到页面的指定锚点位置)
(二)客户端HTTP请求
1. 客户端向服务端发送一个HTTP请求消息
,格式如下:
2. 请求的方法
根据HTTP标准:
HTTP0.9: 只有基本的文本GET功能
HTTP1.0 : 完善的请求/响应模型,并且将协议补充完整,有三种请求方法: GET ,POST和HEAD方法
HTTP1.1 : 在1.0的基础上进行更新,有5种请求方法: OPTIONS , PUT ,DELETE。,TRACE和CONNECT方法。
方法解析:
get: 请求指定的页面信息,并返回实体主体
head: 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
post: 向指定资源提交数据进行处理请求(eg:提交表单或者是上传文件),数据被包含在请求体中,post请求可能会造成新的资源的建立,或者是已有资源的修改。
put: 从客户端向服务器传送的数据取代指定文档中的内容
delete: 请求服务器删除指定的页面
connect: HTTP/1.1协议中预留给能够将连接改成管道方式的代理服务器
options: 允许客户端查看服务器的性能
trace: 回显服务器收到的请求,用于测试或者是诊断
常用请求方法解析:
import requests
#get 方法
url = 'http://www.baidu.com'
response = requests.get(url)
print(response.text)
print(response.content)
# print(response.json())
# post
url = 'http://httpbin.org/post'
response = requests.post(url,data={'name':'westos'})
print(response.text)
# put
url ='http://httpbin.org/put'
response = requests.put(url,data={})
运行结果:
(ps: get与post
get是从服务器上获取数库,post时向服务器发送传送数据
get请求参数会显示在url上,即:“get”请求的参数是URL的一部分
post请求的参数在请求体中,消息的长度没有限制兵器我以隐式的方式进行发送,通常用来向HTTP服务器提交量比较大的数据(比如请求中包含许多参数或者文件上传操作)请求的参数包含在“content-type” 消息中,指明该消息体的媒体类型和编码)
request小案例:
实验代码如下:
import requests
def searchBaidu():
keyword = input("请输入需要搜索的关键字:")
baiduUrl = 'https://www.baidu.com'
params = {
'wd':keyword
}
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60'
}
try:
response = requests.get(baiduUrl,params=params,headers= headers)
response.raise_for_status()
response.encoding = response.apparent_encoding
except Exception as e:
print("[-] 爬取失败", e)
else:
print('[+]' +response.url,"爬取成功")
print(len(response.text))
if __name__ == '__main__':
searchBaidu()
运行结果:
3. 常用的 请求报头
Host: 主机和端口号
Connection: 客户端与服务器连接,默认为keep-alive
user-agent: 客户浏览器的名称
accept: 浏览器或者是其他客户端可以接受的MIME文件类型
Referer: 表明产生请求的网页来自于哪个URL
Accept-Encoding: 指出浏览器可以接受的编码方式
Accept-Language: 语言种类
Accept-Charset: 字符编码
Cookie: 浏览器用这个属性向服务器发送Cookie
Content-type: post 请求里面用来表示的内容类型
(三)HTTP响应
1. HTTP响应的组成
Http响应由四部分组成: 状态行,消息报头,空行,响应正文
2. 响应状态码
常见的响应状态码:
200: 请求成功
302: 请求页面临时转移至新的URL
307和304: 使用缓存资源
404: 服务器无法找到请求页面
403: 服务器拒绝访问,权限不够
500: 服务器遇到不可预知的情况
3. Cookie和Session
服务器和客户端的交互过程限于请求/响应的过程,在下一次的请求中,服务器会认为是新的客户端,为了维护他们之间的链接,让服务器知道这是前一个用户发送的请求。必须在一个地方,保存客户端的信息
Cookie: 通过在客户端记录的信息确定用户的身份
Session: 通过在服务器端记录的信息确定用户的身份。
项目实现: 图片下载器
需求分析: 想要获取照片,但是不想直接上网搜,并且想要能够自动下载
效果展示:
代码实现:
import re
import requests
import os
def downloadPictu(html, keyword):
pic_url = re.findall('"objURL":"(.*?)",', html, re.S)[:5]
count = 0
print('找到关键字:' + keyword + '的图片,现在开始下载')
for each in pic_url:
# print("正在下载第" + str(count + 1) + '张图片,图片地址为:' + str(each))
try:
headers = {
'user - agent': 'Mozilla / 5.0 (Linux;Android 6.0;Nexus 5 Build / MRA58N)'
'AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 59.0.3071.109'
' Mobile Safari / 537.36'
}
responce = requests.get(each, timeout=10, headers=headers)
except requests.exceptions.ConnectionError:
print('[错误] 当前图片无法下载')
continue
except Exception as e:
print('[错误] 当前图片无法下载')
print(e)
continue
else:
if responce.status_code != 200:
print("访问失败:", responce.status_code)
continue
if not os.path.exists(imgDir):
print("正在创建目录", imgDir)
os.mkdir(imgDir)
posix = each.split('.')[-1]
if posix not in ['png', 'jpg', 'gif', 'jpeg']:
print("下载失败, 后缀名错误")
continue
print("正在下载第" + str(count + 1) + '张照片,图片地址:' + str(each))
name = keyword + '_' + str(count)+ '.' + posix
filename = os.path.join(imgDir, name)
count += 1
with open(filename, 'wb')as f:
f.write(responce.content)
if __name__ == '__main__':
imgDir = 'pictures'
word = input("Input key word:")
url = 'http://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gb18030&word=' + word
try:
responce = requests.get(url)
except Exception as e:
print(e)
content = ''
else:
content = responce.text
downloadPictu(content, word)