爬虫基础(一)

爬虫

爬虫的本质:通过程序向网站发送请求,并得到响应的数据,最后将数据解析出来。

第一个小爬虫

utllib包中的request.py文件中导入urlopen函数。

这个函数的作用:接收一个地址字符串或请求对象,返回一个响应。

函数原型:def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,*, cafile=None, capath=None, cadefault=False, context=None)

from urllib.request import urlopen

url = "http://www.baidu.com"
# 向网址发送一个请求,并得到其响应
resp = urlopen(url)
# 将响应信息读出来
result = resp.read()
print(result)

结果:

b'<!DOCTYPE html><!--STATUS OK-->\n\n\n    <html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta content="always" name="referrer"><meta name="theme-color" content="#2932e1"><meta name="description" content="\xe5\x85\xa8\xe7\x90\x83\xe6\x9c\x80\xe5\xa4\xa7\xe7\x9a\x84\xe4\xb8\xad\xe6\x96\x87\xe6\x90\x9c\xe7\xb4\xa2\xe5\xbc\x95\xe6\x93\x8e\xe3\x80\x81\xe8\x87\xb4\xe5\x8a\x9b\xe4\xba\x8e\xe8\xae\xa9\xe7\xbd\x91\xe6\xb0\x91\xe6\x9b\xb4\xe4\xbe\xbf\xe6\x8d\xb7\xe5\x9c\xb0\xe8\x8e\xb7\xe5\x8f\x96\xe4\xbf\xa1\xe6\x81\xaf\xef\xbc\x8c\xe6\x89\xbe\xe5\x88\xb0\xe6\x89\x80\xe6\xb1\x82\xe3\x80\x82\xe7\x99\xbe\xe5\xba\xa6\xe8\xb6\x85\xe8\xbf\x87\xe5\x8d\x83\xe4\xba\xbf\xe7\x9a\x84\xe4\xb8\xad\xe6\x96\x87\xe7\xbd\x91\xe9\xa1\xb5\xe6\x95\xb0\xe6\x8d\xae\xe5\xba\x93\xef\xbc\x8c\xe5\x8f\xaf\xe4\xbb\xa5\xe7\x9e\xac\xe9\x97\xb4\xe6\x89\xbe\xe5\x88\xb0\xe7\x9b\xb8\xe5\x85\xb3\xe7\x9a\x84\xe6\x90\x9c\xe7\xb4\xa2\xe7\xbb\x93\xe6\x9e\x9c\xe3\x80\x82">

截取一小段获取的信息,可以从中看出响应到的是一个html,并且数据是字节编码的!

对字节进行解码:

# 从上面获取的响应中可以看到,charset用的utf-8
result = result.decode("utf-8")
print(result)
<!DOCTYPE html><!--STATUS OK-->
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta content="always" name="referrer"><meta name="theme-color" content="#2932e1"><meta name="description" content="全球最大的中文搜索引擎、致力于让网民更便捷地获取信息,找到所求。百度超过千亿的中文网页数据库,可以瞬间找到相关的搜索结果。"><link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /><link rel="search" type="application/opensearchdescription+xml" href="/content-search.xml" title="百度搜索" /><link rel="icon" sizes="any" mask href="//www.baidu.com/img/baidu_85beaf5496f291521eb75ba38eacbd87.svg"><link rel="dns-prefetch" href="//dss0.bdstatic.com"/><link rel="dns-prefetch" href="//dss1.bdstatic.com"/>

web请求剖析

从上面可以看到,发送一个请求然后服务器会返回给你html源代码。

然而上面那种是将数据嵌入到html代码中(渲染)然后返回源代码(在服务端这就是一个静态页面)

但是渲染有两种:

  1. 服务端渲染:在服务器的就是静态html文件,直接返回。
  2. 客户端渲染:在服务器中的只是一个html骨架,响应回去的也是一个html骨架。再通过Ajax进行请求获取数据,渲染 (通过js) 到页面中。

但是我们获取的只是第一次的响应,这个响应中只有骨架。而渲染发生在响应之后,所以我们得不到数据。

渲染确实发生了(但是我们捕获不到),这说明js起作用,那么ajax就起作用了。ajax起作用了那我们就可以通过捕获包的方式获取数据(数据都在包中,包括图片、json数据)。
在这里插入图片描述

从上面图中可以看出,就算是客户端渲染,只要我们抓取到包也是可以捕获到数据的!

所以我们只需要发送请求到那个可以获得数据响应的请求中就可以获得数据,并且数据都是规则格式的数据!

HTTP协议

在网络原理中我们学过,HTTP协议是网络传输中遵守的一种协议。

HTTP(Hyper Text Transfer Protocol)超文本传输协议。用于服务端传送超文本到客户端。服务器与客户端之间数据交换遵守HTTP协议(服务器实际上也是一个计算机)。

HTTP协议把一条消息分为了三大块(无论是请求还是响应)

  1. 在请求中:

    请求行 -> 请求的方式 请求的url地址 协议
    请求头 -> 存放一些服务器要使用的附加信息
    
    请求体 -> 放一些请求参数
    
    请求方式:get/post等
    请求头中:用的什么浏览器,浏览器对数据的要求,反爬等信息
    
    请求体中:请求携带的那些参数
    
  2. 在响应中:

    状态行 -> 状态码 协议
    响应头 -> 放一些客户端要使用的附加信息
    
    响应体 -> 服务器返回的内容(HTML、json)等
    
    状态码:请求是否成功等状态码
    响应头:例如图片等
    响应体:包含响应的内容
    

在这里插入图片描述

在我们爬虫的时候要注意一下响应头与请求头,这里面往往包含一些重要的数据!
在这里插入图片描述

请求头中常见的一些重要内容(爬虫需要):

  1. User-Agent:请求载体的身份标识(用啥发送的,如浏览器信息)
  2. Referer:防盗链(这次请求是哪个页面来的,反爬的时候会使用)
  3. cokkie:本地的一些cookie信息

响应头中常见的一些重要内容:

  1. cookie:本地的一些键值对(包含用户登录信息、反爬的token等)
  2. 还有各种模型奇妙的字符串(一般都是token字样,防止工具与反爬)

requests模块入门

爬虫的三大件:

  1. url
  2. 请求方式
  3. 请求参数

入门案例1:获取响应信息+小小反反爬

这是第三方模块。之前在第一个小爬虫的例子中使用了python自带的request包中的urlopen,但是这也就只能获取到响应,对于响应的信息它并没有提供方法供我们解析响应。这导致我们需要手动写程序去解析响应信息!

所以使用第三方的requests模块可以快速开发,处理响应信息。

import requests

# 百度查找周杰伦
url = "https://cn.bing.com/search?q=周杰伦"
# 使用get方式发送请求。看着是不是类似jQuery?
resp = requests.get(url)
# 直接输出resp可以查看响应状态
print(resp)

# 获取页面源代码
print(resp.text)

resp.close()

可能服务端判断出来你是程序请求,而不是人。获取到的响应是用户您好,我们的系统检测到您网路中存在异常访问请求

可以使用响应头中的User-Agent来使得程序更像浏览器发出的请求(这样服务端就不一定可以判别出你是程序还是人)。
在这里插入图片描述

在请求头字典中添加一个元素:user-agent。这样可以使得程序发送的请求的头信息中包含浏览器信息,实现一个小小的反反爬

url = "https://cn.bing.com/search?q=周杰伦"

# 设置一个字典,这个字典是头信息字典
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36'
}

# 将字段放到函数中,参数为请求头
resp = requests.get(url, headers = headers)
print(resp)

print(resp.text)

resp.close()

入门案例2:具有指向的爬取数据+获取动态页面中的数据

在豆瓣中有的数据是第一次响应就发送过来HTML数据,但是这些数据只是一个框架。真正的数据是ajax动态请求得到的响应的数据。但是这些数据并不是你代码发送请求得到的响应中可以有的,这是第二次ajax发送的请求。
在这里插入图片描述

但是,我们可以通过XHR中的包查看ajax发送的请求是哪个以及获得的响应的数据是哪个!
在这里插入图片描述

这些数据就是第一幅图中最近入门电影中动态的数据。

从Headers中可以看到它的URL以及它的请求方式以及携带的参数!
在这里插入图片描述

url = 'https://movie.douban.com/j/search_subjects'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
}

params = {
    "type": "movie",
    "tag": "热门",
    "page_limit": 50,
    "page_start": 0
}

resp = requests.get(url, headers = headers, params = params)

# 服务端响应给客户端的请求信息中的url
# 可以看到响应中有request,其中有请求的三大件。并且响应中也有响应的三大件
print(resp.request.url)
print(resp.json())
# 将json转换为字典方便程序使用
print(dict(resp.json()))

resp.close()

可以看到响应中有request,其中有请求的三大件(请求行、请求头、请求体)。并且响应中也有响应的三大件(响应行、响应头、响应体:响应体就是resp.text的信息)。


注意!动态页面中大多数使用的服务端数据库查找是分页查找,如果你获得的数据可能特别少,并且请求参数中有start等参数,你就可以循环更改参数发送请求获得更多的响应数据!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值