【爬虫原理】

《爬虫》

1、爬虫的概念

​ 概念:(spider,网络蜘蛛)通过互联网上一个个的网络节点,进行数据的提取、整合以及存储

分类:

通用爬虫(了解)

​ 主要用于搜索引擎(百度、Google ,搜狗等)

​ 搜索引擎的工作原理:

​ 核心部分:通过爬虫按照互联网的拓扑结构,进行批量的数据抓取,然后进行数据清洗与整合,然后按照一定的次序存入百度的数据库集群

​ 检索部分:实质上就是一个web系统,给用户提供一个检索平台

​ 搜索引擎获取数据的方式:

​ 1)通过通用爬虫

​ 2)主动的提交自己的网站

​ 3)通过竞价排名(信息排名:1、流量 2、竞价)

​ 4)搜索引擎和DNS的运营商合把一些有价值的网站收录过来

​ robots协议:

​ robots协议不是技术层面的协议,只是一个君子协定;首先在爬取一个网站的时候,第一步就是访问这个网站的robots.txt文件,在这个文件中规定了那些东西能爬哪些东西不能爬,爬虫要严格遵守,只爬取允许的内容,不要去爬取不允许的内容,搜索引擎爬虫一定遵守robots协议;我们写的话可以不遵守。

聚焦爬虫

​ 根据客户的需求,定制一些针对性比较强的爬虫

​ 工作原理:

​ 1、数据提取(抓取)

​ 技术:http协议等应用层协议

​ 反爬:用户代理、IP禁止、验证码、会话处理等

​ 2、数据的分析

​ 遇到的数据:html、json、xml、js数据

​ 反爬:js动态加载、js加密、后台加密等

​ 3、数据的存储

​ CSV数据、json数据、关系型数据库、非关系型数据库

​ 爬虫主要研究如何对付反爬

​ 学习内容:

​ 1、python

​ 2、相关的框架

​ urllib、requests、scripy等数据的抓取

​ 正则、xpath、bs4、selenium等

​ 3、分布式部署

2、HTTP协议

​ 1、什么是HTTP协议?

​ 1)是一个基于请求与响应的应用层协议,底层协议是TCP保证了整个传输过程的可靠性 2)通过url来进行客户端与服务器的交互(url解释:统一资源定位符,用于定位互联网上资源的位置,格式,协议://主机名.域名:端口号/路径名…?参数1=值1&参数2=值2&…#锚点)3)是一种C/S(B/S是一种特殊的C/S结构)模式的协议,客户端发起请求,服务端处理请求并响应 4)它是一种无状态的协议,它通过cookie或者session来处理会话信息

​ 2、http的过程

​ 1)创建TCP链接:三次握手,客户端首先向服务器发出一个是否同意创建连接的请求,然后服务根据自己的任务量决定是否创建,并且把是否创建连接的相关信号返回给客户端,然后客户端如果接到了同意创建连接的信号,就正式的发起一个创建连接的信号,并且带上http协议的报文。通过三次握手客户端和服务器之间建立齐了一条数据通路,就可以保证HTTP协议的可靠传输

​ 2)客户端向服务器发起HTTP请求:通过url把参数以及请求头信息传递给服务器,常见的请求方式有4中,常用的是get和post

​ 请求头:包含了本次请求的相关配置信息(比如:主机、cookie、数据格式等),决定了客户端和服务之间数据交流的方式与格式

​ 请求体:就是参数,也即是客户端要想服务器提交的数据

​ get请求和post请求的区别:

​ get请求参数拼接在url后面的,post请求参数不体现在url中(一般直接通过表单提交);get请求数据量有限制(不同的浏览器对url的长度都有不同的限制),post请求是没有限制的

​ 3)服务器处理请求,并且把数据响应出去

​ 4)判断数据是否传输结束,如果结束,四次挥手断开TCP链接

3、工具

​ windows、Linux、fiddler

4、面试题

​ 1、请您解释一下http协议?

​ 2、什么是http无状态,如何去解决?

​ 3、https协议和http协议的区别,和它的优势

​ 4、get请求和post请求的区别

​ 5、http协议的常见状态码,及其含义

​ 6、https协议如何配置证书?

5、urllib 框架*

首先在pycharm的Terminal中pip install urllib

#从urllib中导入请求模块
from urllib import request
# urllib是python提供的一个用于发起和处理http请求与响应的框架,后期的一些框架比如requests、scrapy等都是基于它
---------------------------------------------------------------
url = "http://www.baidu.com/"

# 1、urlopen()方法,用于打开一个远程的url链接,并且向这个连接发出请求,获取响应结果
response = request.urlopen(url=url)
print(response) # <http.client.HTTPResponse object at 0x0000023F0B8995C0> # 返回值是一个http响应对象
# 这个响应对象中记录了本次http访问的响应头和响应体
print(response.headers) # 打印响应头
print(response.url)
print(response.status)
---------------------------------------------------------------
#读取响应体
#(1)读取所有的响应体并且整合成一个二进制字符串
res = response.read()
#(2) 对响应体进行解码
res.decode("utf-8")
#(3)读一行
res = response.readline()
#(4)如果有多个读取,则后面的读取接着前面的读
res = response.readline()
#(5)读取多行,得到一个列表,每个元素是一行
res = response.readlines()
===============================================================
# 2、urlretrieve(url=xxx,filename=xxxx)
# 打开url这个链接并且发起请求,获得响应并且把响应的结果保存在filename中
res = request.urlretrieve(url=url,filename="./baidu.html")
print(res) # ('./baidu.html', <http.client.HTTPMessage object at 0x000001F484EC3E80>)
request.urlretrieve(url="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1555914088353&di=c3267c16c1f03581b36735abde4516ae&imgtype=0&src=http%3A%2F%2Fp0.ifengimg.com%2Fpmop%2F2018%2F1102%2FAEC850C10346EE07EFCAA9052712BAACC563FAE9_size95_w1080_h720.jpeg",filename="./zhiling.jpg")
===============================================================
# 3、urlencode()方法,对url进行编码

url = "https://www.baidu.com/s?"
      # "ie=utf-8&wd=空姐"  # urllib这个框架的url中不能出现汉字,只能出现ascii码字符
# ie=utf-8&wd=%E8%80%81%E7%8E%8B

# 导入parse框架
from urllib import parse
# parse是urllib中用于处理url的工具
# 1)把参数写成字典的形式
dic = {
   
   "ie":"utf-8","wd":"奔驰"}

# 2)用parse的urlencode方法来编码
params = parse.urlencode(dic)
print(params) # ie=utf-8&wd=%E5%A5%94%E9%A9%B0
# 3)将编码以后的参数拼接到url中
url += params
request.urlopen(url=url)

6、user_agent

from urllib import request

url = "https://weibo.cn/"

# request.urlopen(url=url) # urllib.error.HTTPError: HTTP Error 403: Forbidden
# 反爬:【用户代理】web开发中,同一个url往往可以对应若干套不同的数据(或者界面),后台可以根据发起请求的前端的用户代理的不同,而决定应该给前端做出什么样的响应;如果检测到没有用户代理可以拒绝访问

# 解决方案:伪装请求头
# 1) 创建Request对象
req = request.Request(url=url,headers={
   
   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36',
                                       'cookie': '_T_WM=e75d066bb30fae02106ed2a058e3ba08; SUB=_2A25xuV-TDeRhGeBN7FIR9izJyTSIHXVTQmHbrDV6PUJbktANLVjZkW1NRFYvPzVjmAtKAY7Kppc7xOninRZqgesm; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9W59rVpGeZ7yg7I7HR0hyYPg5JpX5KzhUgL.Foq0S057Sozfeon2dJLoI05LxKML1heLB-BLxKqL1heL1h-LxKML1-2L1hBLxKqLBoeLBKzLxKqLBoeLBKz41K.t; SUHB=04WeHU67Q84JrJ'})
# 用Request对象可以给请求加上请求头,使得请求伪装成浏览器等终端

# 2) 用加入了请求头的请求对象发起请求
res = request.urlopen(req)
print(res.status)

# 写入本地
with open("wei.html","wb") as fp:
    fp.write(res.read())

7、 post

from urllib import request,parse


url = 'https://fanyi.baidu.com/sug'

# 1)请求头
headers = {
   
   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36'}
# 2) 请求体
data = {
   
   "kw":"a"}
# post请求的请求体和get请求格式一样(参数1=值1&参数2=值2&...)
data = parse.urlencode(data).encode("utf-8") # post提交的数据是二进制,需要用utf-8编码

print(data)
# 3)用前面的请求头、请求体和url来创建请求对象
req = request.Request(url=url,headers=headers,data=data)

# 发起请求
res = request.urlopen(req)
print(res.read())

8、 会话处理

from urllib import request,parse

# 【注意】采用Request+urlopen的机制无法处理会话信息,如果爬虫中带会话处理,需要借助于handler+opener
# 【采用handler+opener机制处理会话问题】
# 导入cookie初始化工具
from http import cookiejar # 处理cookie的时候这个对象就可以存储cookie信息
# 1) 初始化一个cookie对象
cookie = cookiejar.CookieJar()
# 2) 创建一个handler对象,携带上cookie
handler = request.HTTPCookieProcessor(cookie)
# 3) 创建一个opener对象携带上handler
opener = request.build_opener(handler)

# 请求头
headers = {
   
   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36'}

# 登录接口
login_url = 'http://www.jokeji.cn/user/c.asp?'
# u=bobo666&p=a&sn=1&t=big
# 处理登录接口
dic = {
   
   'u':'bobo666','p':'a12345678','sn':'1','t':'big'}
params = parse.urlencode(dic)
login_url += params
# 创建一个登录请求对象
login_req = request.Request(url=login_url,headers=headers)
# 发起请求以登录
# res = request.urlopen(login_req)
# 用opener来发起请求
res = opener.open(login_req) # 此时发起的请求结束以后,相关的cookie信息就会被opener的handler通过cookiejar对象保存

print(res.read().decode('utf-8'))
# 个人主页url
page_url = "http://www.jokeji.cn/User/MemberCenter.asp"

page_req = request.Request(url=page_url,headers=headers)

# res = request.urlopen(page_req) # 虽然前面已经登录成功,但是cookie信息没有被保存,仍然不成功
res = opener.open(page_req)
with open("joke.html","wb") as fp:
    fp.write(res.read())

9、 正则

import re

string = '''If you have great talents, industry will improve them; 
if you have but moderate abilities,
industry will supply their deficiency.'''

# 1)元字符
# 普通字符、字母、下划线、数字等ascii码字符
pat = r'a'
# 非打印字符
pat = r'\n'
ret = re.findall(pattern=pat,string=string)

# 2)通配符
# y用某些特殊的字符,来表示一类字符串
'''
\w  任意的字母、数字、下划线
\W  任意的非字母、数字下划线
\d  任意的数字
\D
\s  空白
\S
[abc]  匹配a、b或c
[a-fA-P1-5] 匹配a-f或A-P或者1-5中的任意一个
[^abc] 任意一个非abc的字符串
'''
pat = r'[^abc]'
pat = r'[^a-f]'
pat = r'\w'
ret = re.findall(pattern=pat,string=string)
print(ret)
# 特殊字符
'''
.   任意的可见字符
^   从字符串的开头匹配
$   字符串以后什么为结尾
+   重复一到多次
*   重复0到多次
?  重复0或者1次
{m} 重复每次  {,m}至多重复m次   {m,}  {m,n}
'''
pat = r'^If.+\n.+\n.+'
# pat = r'^If.+$'
ret = re.findall(pattern=pat,string=string)
print(ret)

# 3) 模式修正
# 如果要进模式修正需要用complile将正则表达式创建成一个正则对象
# re.S  把多行字符串看成一行
# re.M  把多行字符串拆成多个单行来处理
# re.I  忽略大小写
pat = re.compile(r'^If.+',re.S)
ret = pat.findall(string)
print(ret)

# 4) 贪婪模式和懒惰模式
string = "afadfasadfafapyasdfadsfapyafadpypyafasdfapyasfasdfdaspyafafdaspyrtyui"
pat = re.compile(r".*py") # 贪婪模式:按照规则进行寻找一直找到最后一个符合规则字符串为止
pat = re.compile(r".*?py") # 懒惰模式:按照规则进行寻找只要找到符合规则的字符串就立即停止
ret = pat.findall(string)
print(ret)

10、爬取sucai示例*

from urllib import request,parse
from time import sleep
import re

# 1、【数据的获取】
# 封装一个函数,用于将url转化成一个请求对象
def request_by(url,page):
    headers = {
   
   
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36'}
    if page==1:
        page_url = url + ".html"
    else:
        page_url = url +"_"+ str(page) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值