第三章 网络爬虫

网络架构

1.1互联网工作原理

  1. IP 地址:任何连接网络的计算机都需要一个唯一的地址标记它
    IP地址由四部分被分隔的数字序列组成,如:192.129.2.10,取值范围在0到255
  2. 域名: IP地址的别名,使其更容易记忆
  3. 搜索引擎与浏览器的区别
    • 浏览器是一个接受并显示网页的软件
    • 搜索引擎是一个帮助用户搜索其他网页的网站

1.2网站三大支柱

HTTP/HTTPS

  1. 定义:一种 超文本传输协议
  2. 请求过程
    1. 用户在浏览器输入网址,浏览器向网页服务器发送请求
    2. 网页服务器接到请求,处理请求,产生响应
    3. 浏览器接受网页服务器的HTML内容,渲染展示给用户
  3. **HTTP安全吗?
    • 明文传输,易被窃听或篡改,不够安全
    • 解决方法:HTTPS 在HTTP基础上加上SSL/TLS协议,依靠SSL证书来验证服务器身份,确保数据传输安全

URL

俗称网址

url的组成

以此为例:
http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument

  • HTTP是协议
  • www.example.com 是域名
  • :80是端口
  • path/to/myfile.html是网络服务器上的资源路径
  • key1=value1&key2=value2是提供给网络服务器的额外参数
  • #SomewhereInTheDocument 是资源本身的另一部分锚点,类似于书签,用来为浏览器显示位于该书签位置的内容和方向

HTML

  • 超文本标记语言
  • 组成:<开始标签>被标记的内容<结束标签/>
  • 元素开始结束加被标记内容就是一个完整的元素
  • 空元素:只有一个标签用来在该位置插入一些东西

术语区分

术语含义
IP地址唯一标识互联网计算机的逻辑地址
域名IP地址的别名,方便记忆
URL俗称网址,格式为<协议>://<域名/IP>:<端口号/路径>

网络爬虫概述

2.1网络爬虫

  1. 定义自动提取网页的程序,主要目的是将互联网上的网页下载到本地,并 提取相关数据
  2. 网络爬虫工作流程 ![[网络爬虫工作流程.png]]

2.2网络爬虫的类型

1. 通用网络爬虫——从一些种子URL扩充到整个Web

  1. 全网爬虫流程![[全网爬虫流程.png]]
  2. 实用范围:主要为 搜索引擎和大型web服务商采集数据。爬行范围和数量巨大,对 爬行速度和储存空间要求高,对 爬行页面顺序要求低,通常采用 并行工作方式。
  3. 通用网络爬虫真的通用吗? 有哪些局限性
    1. 包含大量用户不需要的网页
    2. 不能很好的获取 信息密集的数据
    3. 基于关键字检索,一般不支持语义信息查询和 搜索引擎智能化

2.聚焦网络爬虫——选择性爬取相关主题页面

  1. 主题网络爬虫流程![[主题网络爬虫流程.png]]
  2. 优点节省爬虫时所需的带宽资源和服务器资源
  3. 特点:按照预先定义好的主题 有选择的进行爬取,相较于 通用爬虫,增加了 目标的定义过滤机制

3.增量式网络爬虫——只爬取新/变化的网页

  1. 优缺点有效减少下载量及时更新已爬网页减小时间和空间消耗。但 增加爬行算法的复杂度和实现难度

4.深层网络爬虫——爬取隐藏的深层页面

  1. 深层页面指普通搜索引擎难以发现的信息内容页面,信息量更多,质量更高。
  2. 流程:解析url -> 分析页面是否包含深层页面入口的表单 -> 模拟人的行为对表单进行分析填充提交

2.3反爬机制

为什么要有反爬机制?

  1. 不愿自己数据被别人免费获取
  2. 简单爬虫数据采集速度快,可能会因为 请求太多造成网站服务器不能正常工作

网络爬虫基础

requests 库

# 导入requests库
import requests
response = requests.get(url,params,headers,cookies,auth,timeout)
print(response.text) #返回文本
print(response.content) #返回二进制数据
response1 = requests.post(url,data = {key:value},json = {key:value},args)

参数
get:
url - 请求对象的URL地址
params - get请求的参数
headers - 请求头信息
cookies - 客户端记录的用户身份信息的参数
auth - authobject启用基本http身份验证(没用到过)
timeout - 请求超时的设置,浮点数表示
post:
data - 要发送到指定url的字典、元组、列表或文件对象
json - 发送给指定url的json对象
args - 其他参数,如cookies、headers、verify等
Cookie与Session
cookie:通过在 客户端 记录的信息确定用户的身份
session:通过在 服务器 端记录的信息确定用户的身份

常见的响应状态码
  • 200——请求成功
  • 301——资源被永久转移
  • 307——浏览器内部重定向
  • 401——需要出入账号和密码访问资源
  • 403——请求被禁止
  • 404——请求资源不存在
  • 500——内部服务器错误
  • 418——网站发现你是爬虫
服务器端渲染 VS 客户端渲染
  • 服务器端渲染:返回前端 完整的HTML文件 浏览器拿到html后直接解析展示
  • 客户端渲染前后端分离的开发模式,后端不提供完整的html页面而是提供一些api使得前端可以获取json数据(通过Ajax请求 )拿给前端拼接,最后展示在浏览器,好处是前端专注ui开发,后端专注逻辑开发
  • Ajax请求异步从服务器请求数据更新到网页

python读写

with open(文件名,打开方式) as f: #'r'只读,'w'只写,会覆盖前面写的。用with open不需要考虑关闭文件的事,自动关闭

反爬机制和反反爬策略

  1. 常见的反爬机制
    IP封锁,验证码验证,ua检测,js数据加密等
  2. 策略
    1. IP代理:绕过封锁
    2. ua伪装:模拟浏览器
    3. 请求延迟:模仿用户操作
    4. 数据解析技巧:高校提取信息
    5. cookie和session跟踪:添加cookie参数

美丽汤BeautifulSoup

特点

  1. api简单,功能强大
  2. 支持多种解析器
  3. 自动实现编码转换
    补充解析器:把某种格式的文本转换成某种数据结构

基本使用

# 导入
from bs4 import BeautifulSoup

# 初始化beautifulsoup类
soup = BeautifulSoup(html,'解析器')

选择器

  1. 节点选择器
# tag对象:<tag对象>
soup.tag # 有多个相同节点值返回第一个
#返回节点元素

soup.tag.name # 返回字符串,tag对象的名称
soup.tag.attrs # 返回字典,<tag 属性>,返回属性
soup.tag.string # 返回字符串,tag里面标记的内容

#嵌套选择
# <tag><tag2>text</tag2></tag>
soup.tag.tag2
  1. css选择器
soup.select()
#'.'类选择器
#'#'id选择器
#标签选择器
# id选择器 - 用#定位元素 以id定位第一个ul节点
print(soup.select('#list-1'))

# 类选择器 - 用.定位元素 以class定位第二个ul节点
print(soup.select('.list-small'))

# 标签选择器 - 使用标签名定位元素 以标签名定位ul节点
print(soup.select('ul'))

# 定位class属性值为list,同时id属性值为list-1的所有节点
print(soup.select('.list' '#list-1'))
# 定位第一个ul节点的子级li节点
print(soup.select('#list-1 .element'))
  1. 方法选择器
soup.find_all(name,attrs,kwargs,text,limit,recursive) #返回所有
soup.find #返回第一个

name参数用来接收tag名称,有四种形式:字符串,正则,列表和True

attrs参数用来接收属性的键值对字典

kwargs参数用来接收常用属性的变量赋值的形式 例如:id=‘link1’ ,class_=“sister”

text参数用来接收文本信息

limit参数用来限制返回结果的数量

recursive参数用来决定是否获取子孙节点

总结

原理 1. 实例化beautifulsoup对象,并将页面源代码加载到该对象中去
2.通过bs对象的相关属性方法进行标签定位和数据提取
如何实例化?
1. 将本地html文档加载到对象中去
2. 将互联网获取的页面源码加载到对象中(两种方法) soup
BeatifulSoup(page_text,‘lxml’) bs的属性和方法
3. soup.tagname
(tagname代表标签名,如soup.div等等)
2.soup.find()
(1)soup.find(‘div’) = soup.div
(2)属性定位soup.find(‘标签名’,标签属性(如:class_等)=‘具体参数’)
3.soup.find_all(‘标签名’) 符合标准的所有标签名
4.soup.select(‘’)返回为列表
(1)引号内填某种选择器(类选择器等)如:class,id,等
(2)层级选择器’>‘代表一个层级,’ '表示多个层级。
5.获取标签之间的文本数据:
(1)soup.a.text/string/get_text()其中text和get_text()可以获得标签的所有内容,string只能得到直系标签的内容
6.获取标签的属性值

soup.a['属性']
CSV文件写入
  1. 列表写入
import csv

header = ['姓名', '年龄', '城市']
data = [
    ['小明', '25', '北京'],
    ['小红', '30', '上海']
]

with open('data.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.writer(f)  # 创建writer对象
    writer.writerow(header)  # 写入单行(标题)
    writer.writerows(data)   # 写入多行数据(嵌套列表)

  1. 字典写入
import csv

fieldnames = ['姓名', '年龄', '城市']  # 定义字段名(表头)
data = [
    {'姓名': '小明', '年龄': '25', '城市': '北京'},
    {'姓名': '小红', '年龄': '30', '城市': '上海'}
]

with open('data.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)  # 创建DictWriter对象
    writer.writeheader()  # 写入表头
    writer.writerows(data)  # 写入多行数据

正则表达式

常用元字符

\d匹配任意数字,等价于[0-9]
\w匹配任意字母数字及下划线
\W非字母数字下划线
\s匹配任意的空白符
\n匹配一个换行符
\t匹配一个制表符
\D非数字
\S非空白符
.匹配除换行符以外的任何字符
^匹配字符串的开始
$匹配字符串的结尾
a|b匹配a或b
[···]匹配字符组中的字符
[^···]匹配非字符组的字符

常用量词

量词作用控制元字符出现次数
*重复0次或多次
+重复1次或多次
重复0次或1次
{m}重复m次
{m,}重复m次或更多次
{m,n}重复m到n次
  • .**: 贪婪匹配
  • .*?*:惰性匹配

正则表达式语法

re.match()——尝试从字符串的 起始位置匹配 一个模式,如果不是起始位置匹配成功返回 none

import re
re.match(pattern,string,flags = 0)
参数描述
pattern匹配的正则表达式
string匹配的字符串
flags标志位,用于控制正则表达式的匹配方式,如:是否区别大小写、多行匹配等等
repl替换的字符串,也可以是一个函数
count模式匹配后替换的最大次数,默认0表示替换所有的匹配
  • re.search()——只要有匹配的后面就不再继续检索,找到一个匹配的就停止
import re
re.search(pattern,string,flags = 0)

re.findall()——在字符串中找到正则表达式所匹配的 所有子串,返回 一个列表,如果有多个匹配模式,返回 元组列表没有匹配就返回 空列表

import re
re.findall(pattern,string,flags = 0)

re.compile()——用于函数编译正则表达式,生成一个正则表达式(pattern)对象(预加载),供match(),search(),findall()等函数使用

re.compile(pattern)
# 其他方法的调用方法改变,如:
re.findall(string,flags = 0)

re.sub()

re.sub(pattern,repl,string,count = 0,flags = 0)

flags的参数

参数意义
re.I忽略大小写
re.S单行模式
re.M多行模式
  • (?P<组名>正则表达式):正则提取/分组匹配
    补充pythony 异常处理
try:
	正常操作
except:
	发生异常,执行这块代码
else:
	如果没有异常执行这块代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值