Python学习从0开始——项目一day01爬虫(二)

news2024/11/14 19:59:16

Python学习从0开始——项目一day01爬虫`(二)`

  • 一、解析response数据
  • 二、json转换
  • 三、文件保存
  • 四、存储json对象
  • 五、完整代码

上一篇

一、解析response数据

在已经知道我们获取图片的最终URL存在于请求响应response中,下一步的重点就放在解析response。
首先给出现在的代码,以下代码暂时删除了图片写入的部分,在文章末尾会给出完整的爬虫代码。

#coding=utf-8
#!/usr/bin/python
# 导入requests库
import requests
# 导入文件操作库
import os
import bs4
from bs4 import BeautifulSoup
import sys
import importlib
importlib.reload(sys)
import re 
import json  
import urllib.parse


# 给请求指定一个请求头来模拟chrome浏览器
global headers
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'}
# 爬图地址
mziTu = 'https://image.baidu.com/'
# 定义存储位置
global save_path
save_path ='./picture'


# 创建文件夹
def createFile(file_path):
    if os.path.exists(file_path) is False:
        os.makedirs(file_path)
    # 切换路径至上面创建的文件夹
    os.chdir(file_path)


# 下载文件
def download(page_no, file_path):
    global headers
    res_sub = requests.get(page_no, headers=headers)
    # 解析html
    soup_sub = BeautifulSoup(res_sub.text, 'html.parser')
    # 获取页面的栏目地址
    all_a = soup_sub.find('div',id='bd-home-content-album').find_all('a',target='_blank')
    count = 0
    for a in all_a:
        count = count + 1
        if (count % 2) == 0:
            print("内页第几页:" + str(count))
            # 提取href
            href = a.attrs['href']
            print("套图地址:" + href)
            res_sub_1 = requests.get(href, headers=headers)
            soup_sub_1 = BeautifulSoup(res_sub_1.text, 'html.parser')
            
# 主方法
def main():
    res = requests.get(mziTu, headers=headers)
    # 使用自带的html.parser解析
    soup = BeautifulSoup(res.text, 'html.parser')
    # 创建文件夹
    createFile(save_path)
    file = save_path
    createFile(file)
    print("开始执行")
    download(mziTu, file)


if __name__ == '__main__':
    main()

在这里插入图片描述
在谷歌浏览器中,折叠代码块,快速定位到我们需要的<script>中,第十三个<script>是linkData所在标签,然后对代码继续修改,在53行添加如下内容:

			# 找到所有的<script>标签
            scripts = soup_sub_1.find_all('script')  
            # 第十三个是linkData所在标签
            script_content = BeautifulSoup(scripts[12].text, 'html.parser').text
            #打印值
            print(script_content)
#终端输出如下
!function(){    window.logid = "7865333382831002903";
    require.async(['albumsdetail:widget/ui/app/app'], function (app) {
        app.setPageInfo({
            word: '%E6%B8%90%E5%8F%98%E9%A3%8E%E6%A0%BC%E6%8F%92%E7%94%BB',
            hasResult: '1',
            albumTab: '%E8%AE%BE%E8%AE%A1%E7%B4%A0%E6%9D%90',
            setId: '409',
            title: '渐变风格插画',
            logo: 'https:\/\/emoji.cdn.bcebos.com\/yunque\/pc_vcg.png',
            coverUrl: 'https:\/\/t7.baidu.com\/it\/u=1819248061,230866778&fm=193&f=GIF',
            totalNum: '314',
            albumLinkRn: '30',
            linkData: '[{\x22pid\x22:144520,\x22width\x22:1200,\x22height\x22:562,\x22oriwidth\x22:1200,\x22oriheight\x22:562,\x22thumbnailUrl\x22:\x22https:\\\/\\\/t7.baidu.com\\\/it\\\/u=1819248061,230866778&fm=193&f=GIF\x22,\x22fromUrl\x22:\x22https:\\\/\\\/www.vcg.com\\\/creative\\\/1274231988\x22,\x22contSign\x22:\x221819248061,230866778\x22},{\x22pid\x22:144521,\x22width\x22:562,\x22height\x22:1000,\x22oriwidth\x22:562,\x22oriheight\x22:1000,\x22thumbnailUrl\x22:\x22https:\\\/\\\/t7.baidu.com\\\/it\\\/u=4036010509,3445021118&fm=193&f=GIF\x22,\x22fromUrl\x22:\x22https:\\\/\\\/www.vcg.com\\\/creative\\\/1147957933\x22,\x22contSign\x22:\x224036010509,3445021118\x22},……]

经过以上操作,成功的获取了linkData所在的<script>,下一步是获取linkData,我们通过正则来获取数据:

			# 使用正则表达式来查找linkData的值  
            link_data_pattern = r"linkData: '([^']*)'"  
            match = re.search(link_data_pattern, script_content)
            #查看输出
            print(match)   
#终端输入
python3 spider.py
#终端输出
<re.Match object; span=(605, 10524), match="linkData: '[{\\x22pid\\x22:144520,\\x22width\\x22>

这看起来并不符合我们的预期,我们期望的输出是linkData里的值。
这时,我们需要关注re.search(),其返回结果是一个捕获组,可以通过group()来获取每一组的数据,group(1) 表示获取第一个捕获组的内容。如果没有捕获组或者索引超出了捕获组的范围,group() 方法会抛出 IndexError 异常。
将输出替换为以下内容:

            print(match.group(1))     
#终端输入
python3 spider.py
#捕获组终端输出
[{\x22pid\x22:144520,\x22width\x22:1200,\x22height\x22:562,\x22oriwidth\x22:1200,\x22oriheight\x22:562,\x22thumbnailUrl\x22:\x22https:\\\/\\\/t7.baidu.com\\\/it\\\/u=1819248061,230866778&fm=193&f=GIF\x22,\x22fromUrl\x22:\x22https:\\\/\\\/www.vcg.com\\\/creative\\\/1274231988\x22,\x22contSign\x22:\x221819248061,230866778\x22},^}

下一步需要将捕获组的内容转为我们可以使用的数据。

二、json转换

为什么要将捕获组转换成json数据,什么情况下需要我们转为json数据?
看上方的捕获组输出,我们能明显的识别出这些数据具有统一的属性,直接截取字符串需要经过多次split或者replace,如果通过属性去获取值,会很便于我们操作。

#继续添加如下内容
			if match:  
                # 获取第一个捕获组的内容
                encoded_link_data = match.group(1)
                print(encoded_link_data) 
                # 解析JSON对象  
                link_data_list = json.loads(encoded_link_data)  
            else:  
                print("未能找到linkData的值")

继续执行代码:

#终端输入
python3 spider.py
#终端输出
Traceback (most recent call last):
  File "/root/Python_02/Python/Day01/learn/spider.py", line 98, in <module>
    main()
  File "/root/Python_02/Python/Day01/learn/spider.py", line 95, in main
    download(mziTu, file)
  File "/root/Python_02/Python/Day01/learn/spider.py", line 70, in download
    link_data_list = json.loads(encoded_link_data)  
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 3 (char 2)

根据提示,我们知道现在无法解析为json数据。我们来看一下json的示例数据格式:

[{
	"name":"a",
	"age":1
},{
	"name":"b",
	"age":2
}]

显而易见,问题出在双引号上,那么下一步就需要将’\x22’字串替换为双引号。

#修改赋值
encoded_link_data = match.group(1).replace('\x22', '"')

此时,我们会发现,经过替换后仍旧报相同的错误,而且终端的输出的encoded_link_data 值和替换前没有区别。
为什么呢?
再来观察’\x22’,我们能发现它是一个转义序列,用于表示一个ASCII值为0x22的字符,即双引号,Python会通过转义序列将其解释为双引号,这就造成实际上是双引号替换双引号,故输出不变。而我们并不需要这种转义,我们需要Python将其解释为普通的字符串。

				#修改赋值,同时替换双引号和斜杠的转义 
                encoded_link_data = match.group(1).replace(r'\x22', '"').replace(r'\\\/', '/')
                #encoded_link_data = match.group(1).replace('\x22', '"')
                print(encoded_link_data) 
                # 解析JSON对象  
                link_data_list = json.loads(encoded_link_data)  
#终端输入
cd Python/Day01/learn/
python3 spider.py
#输出,数据正常
[{"pid":144520,"width":1200,"height":562,"oriwidth":1200,"oriheight":562,"thumbnailUrl":"https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF","fromUrl":"https://www.vcg.com/creative/1274231988","contSign":"1819248061,230866778"},……]

三、文件保存

link_data_list现在已经存储了json数据,我们通过get方法获取对应的URL值,然后发送请求获取响应,继续添加以下内容:

#添加到if match:  里
                for item in link_data_list:  
                    # 提取thumbnailUrl字段的值  
                    thumbnail_url = item.get('thumbnailUrl')
                    res_sub_2 = requests.get(thumbnail_url, headers=headers)
                    soup_sub_2 = BeautifulSoup(res_sub_2.text, "html.parser")
                    print("开始提取图片")
                    file_name = thumbnail_url
                    f = open(file_name, 'ab')
                    f.write(soup_sub_2)
                    f.close()
#终端执行
python3 spider.py
#终端输出
开始提取图片
Traceback (most recent call last):
  File "/root/Python_02/Python/Day01/learn/spider.py", line 103, in <module>
    main()
  File "/root/Python_02/Python/Day01/learn/spider.py", line 100, in main
    download(mziTu, file)
  File "/root/Python_02/Python/Day01/learn/spider.py", line 79, in download
    f = open(file_name, 'ab')
FileNotFoundError: [Errno 2] No such file or directory: 'https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF'

使用初始代码的方法行不通,可能是因为没加文件类型,我们做一些小更改:

                    f = open(file_name+'.jpg', 'wb')

还报错,按照文件的输入输出来说我们的操作是正常的,符合流程的,问题会不会还是出现在文件名?
换个名字试一下。

                    f = open('a.jpg', 'ab')
#终端执行
python3 spider.py
#终端输出
Traceback (most recent call last):
  File "/root/Python_02/Python/Day01/learn/spider.py", line 105, in <module>
    main()
  File "/root/Python_02/Python/Day01/learn/spider.py", line 102, in main
    download(mziTu, file)
  File "/root/Python_02/Python/Day01/learn/spider.py", line 82, in download
    f.write(soup_sub_2)
TypeError: a bytes-like object is required, not 'BeautifulSoup'

虽然还是报错,但是报错内容变了,那现在可以确定,问题出现在文件名,对于Python来说,它本身并不直接限制文件名以"https"开头。但是,当我们试图创建、读取或操作一个文件时,实际上是在与底层的操作系统和文件系统交互。因此,真正限制使用"https"作为文件名开头的因素来自这些底层系统。知道原因后,我们就能解决问题了。
同时根据以上终端输出的内容,可以知道f.write()需要的是字节对象,而不是我们现在赋值的BeautifulSoup类型。继续修改:

            
                    file_name = thumbnail_url.replace(r'https://t7.baidu.com/it/u=','')
                    f = open(file_name+'.jpg', 'ab')
                    f.write(res_sub_2.content)

这次正常执行了,来看一下输出的文件:
在这里插入图片描述

四、存储json对象

 #修改代码
 #添加行,存储数据,json数据以字符串形式存储,不是二进制    
            data = open('sava.txt', 'a')     
            if match:  
                # 获取第一个捕获组的内容
                # 提取匹配到的linkData字符串,字符替换时一定要使用r  
                encoded_link_data = match.group(1).replace(r'\x22', '"').replace(r'\\\/', '/')
                #encoded_link_data = match.group(1).replace('\x22', '"')
                #print(encoded_link_data) 
                # 解析JSON对象  
                link_data_list = json.loads(encoded_link_data)  

                for item in link_data_list:  
                    # 提取thumbnailUrl字段的值  
                    thumbnail_url = item.get('thumbnailUrl')
                    res_sub_2 = requests.get(thumbnail_url, headers=headers)
                    soup_sub_2 = BeautifulSoup(res_sub_2.text, "html.parser")
                    print("开始提取图片")
                    file_name = thumbnail_url
                #    f = open(file_name, 'ab')                    
                #    f = open(file_name+'.jpg', 'ab')
                #    f = open('a.jpg', 'ab')                
                    file_name = thumbnail_url.replace(r'https://t7.baidu.com/it/u=','')
                    f = open(file_name+'.jpg', 'ab')
                #    f.write(soup_sub_2)
                    f.write(res_sub_2.content)
#添加,写入,json转字符串写入
                    data.write(json.dumps(item)+'\n')
                    f.close()
            else:  
                print("未能找到linkData的值")
#关闭输入
            data.close()

在这里插入图片描述

至此,完整的一次爬虫结束。

五、完整代码

代码仅供参考学习使用。

#coding=utf-8
#!/usr/bin/python
# 导入requests库
import requests
# 导入文件操作库
import os
import bs4
from bs4 import BeautifulSoup
import sys
import importlib
importlib.reload(sys)
import re 
import json  
import urllib.parse


# 给请求指定一个请求头来模拟chrome浏览器
global headers
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'}
# 爬图地址
mziTu = 'https://image.baidu.com/'
# 定义存储位置
global save_path
save_path ='./picture'


# 创建文件夹
def createFile(file_path):
    if os.path.exists(file_path) is False:
        os.makedirs(file_path)
    # 切换路径至上面创建的文件夹
    os.chdir(file_path)


# 下载文件
def download(page_no, file_path):
    global headers
    res_sub = requests.get(page_no, headers=headers)
    # 解析html
    soup_sub = BeautifulSoup(res_sub.text, 'html.parser')
    # 获取页面的栏目地址
    all_a = soup_sub.find('div',id='bd-home-content-album').find_all('a',target='_blank')
    count = 0
    for a in all_a:
        count = count + 1
        if (count % 2) == 0:
            print("内页第几页:" + str(count))
            # 提取href
            href = a.attrs['href']
            print("套图地址:" + href)
            res_sub_1 = requests.get(href, headers=headers)
            soup_sub_1 = BeautifulSoup(res_sub_1.text, 'html.parser')            
            # 找到所有的<script>标签
            scripts = soup_sub_1.find_all('script')  
            # 第十三个是linkData所在标签
            script_content = BeautifulSoup(scripts[12].text, 'html.parser').text
            #print(script_content)
            # 使用正则表达式来查找linkData的值  
            link_data_pattern = r"linkData: '([^']*)'"  
            match = re.search(link_data_pattern, script_content) 
            #print(match)   
            #print(match.group(1))     
            data = open('sava.txt', 'a')     
            if match:  
                # 获取第一个捕获组的内容
                # 提取匹配到的linkData字符串,字符替换时一定要使用r  
                encoded_link_data = match.group(1).replace(r'\x22', '"').replace(r'\\\/', '/')
                #encoded_link_data = match.group(1).replace('\x22', '"')
                #print(encoded_link_data) 
                # 解析JSON对象  
                link_data_list = json.loads(encoded_link_data)  

                for item in link_data_list:  
                    # 提取thumbnailUrl字段的值  
                    thumbnail_url = item.get('thumbnailUrl')
                    res_sub_2 = requests.get(thumbnail_url, headers=headers)
                    soup_sub_2 = BeautifulSoup(res_sub_2.text, "html.parser")
                    print("开始提取图片")
                    file_name = thumbnail_url
                #    f = open(file_name, 'ab')                    
                #    f = open(file_name+'.jpg', 'ab')
                #    f = open('a.jpg', 'ab')                
                    file_name = thumbnail_url.replace(r'https://t7.baidu.com/it/u=','')
                    f = open(file_name+'.jpg', 'ab')
                #    f.write(soup_sub_2)
                    f.write(res_sub_2.content)
                    data.write(json.dumps(item)+'\n')
                    f.close()
            else:  
                print("未能找到linkData的值")
            data.close()

# 主方法
def main():
    res = requests.get(mziTu, headers=headers)
    # 使用自带的html.parser解析
    soup = BeautifulSoup(res.text, 'html.parser')
    # 创建文件夹
    createFile(save_path)
    file = save_path
    createFile(file)
    print("开始执行")
    download(mziTu, file)

if __name__ == '__main__':
    main()

本来打算继续写存入数据库相关内容,但是MySQL服务器启动要会员,就只加了写数据到文件里,后续可以通过文件导入到数据库,线上就算了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1596457.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

18.软件定时器

一、简介 软件定时器是指具有定时功能的软件&#xff0c;FreeRTOS 提供的软件定时器允许在创建前设置一个 软件定时器定时超时时间&#xff0c;在软件定时器成功创建并启动后&#xff0c;软件定时器开始定时&#xff0c;当软件定 时器的定时时间达到或超过先前设置好的软件定时…

LOCK、ACC、ON、START的含义及正确使用

背景 前段时间在开发一个远程锁车的需求时&#xff0c;讨论到了电源状态的场景。由于初次进入汽车电子行业&#xff0c;对很多基础概念不清晰。当时听主机厂商的同事介绍一遍后&#xff0c;并不是很理解。于是趁着空闲&#xff0c;给自己充充电&#xff0c;也希望能够帮到有需…

Office 365卡顿怎么办?SD-WAN可以解决

随着数字化浪潮的推进&#xff0c;Office 365等云办公应用已成为企业日常运营不可或缺的工具。然而&#xff0c;许多企业在使用Office 365时遭遇了网络卡顿的难题&#xff0c;给工作人员带来诸多不便。随着SD-WAN技术的成熟和普及&#xff0c;这一难题得到了有效的解决。 Offic…

HarmonyOS实战开发-状态管理、通过使用页面级的状态变量 和应用级的状态变量 来实现应用的状态管理。

介绍 本示例通过使用页面级的状态变量 和应用级的状态变量 来实现应用的状态管理。 效果预览 使用说明 1.点击首页中的基本类型进入对应页面&#xff0c;点击按钮可以更改圆形的颜色&#xff1b;点击查看源码可以展示基本类型功能效果的源码。 2.点击首页中的数组类型进入对…

密码知识汇总

文章目录 密码学知识&#xff23;&#xff29;&#xff21;三要素机密性&#xff08;Confidentiality&#xff09;完整性&#xff08;Integrity&#xff09;可用性&#xff08;Availability&#xff09; 非安全信道的风险以及应对措施风险应对措施使用加密技术&#xff08;防窃…

【第十五届】蓝桥杯省赛C++b组

今年的蓝桥杯省赛已经结束了&#xff0c;与以往不同&#xff0c;今年又回到了8道题&#xff0c;而22&#xff0c;23年出现了10道题 大家觉得难度怎么样&#xff0c;欢迎进来讨论&#xff0c;博主今年没参加哈&#xff0c;大家聊聊&#xff0c;我听听大家的意见和看法哈 试题A:…

【Labelimg标注使用预定义标签】

Labelimg标注使用预定义标签 安装 在环境中pip install labelimg 打开图片文件夹 把预定义标签放在保存文件夹里 选择保存文件夹地址

便宜的dv ssl证书推荐

SSL数字证书是维护互联网安全的重要手段之一。SSL数字证书主要目的是保护客户端和服务器数据传输的安全&#xff0c;防止网站数据在传输过程中被窃取或者篡改。其次&#xff0c;SSL数字证书能够验证网站的身份和合法性&#xff0c;防止用户访问到假冒或钓鱼网站。此外&#xff…

2.MMD关键帧及镜头自定义操作

1. 关键帧操作 如何控制关节移动 在骨骼操作界面打开选择 鼠标左键点击左腿根部的骨骼节点&#xff0c;可以通过右边local的六个键来旋转骨骼 目前红色点圆周外有一个黄色的圈 这是一个微调的动作&#xff0c;它会影响这单个关节而不会影响整个大腿 可以看到大腿微微抬起…

剑指offer之牛客与力扣——前者分类题单中的题目在后者的链接

搜索 [4.12完成] JZ1 LCR 172. 统计目标成绩的出现次数 JZ3 153. 寻找旋转排序数组中的最小值 JZ4 LCR 014. 字符串的排列 JZ5 LCR 163. 找到第 k 位数字 400 动态规划 [4.15完成] JZ2 LCR 161. 连续天数的最高销售额 53 JZ3 LCR 127. 跳跃训练 70 JZ4 LCR 126. 斐波那契…

游戏开发者必看:Perforce Helix Core 的功能特点及游戏开发中的常用工具、典型用例介绍

「不出海&#xff0c;即出局」随着全球化的加速发展&#xff0c;企业出海已成燎原之势。日前&#xff0c;2024 亚马逊云科技出海全球化论坛在深圳成功举办。龙智携手 Perforce 亮相游戏行业展区&#xff0c;展示了Perforce Helix Core如何与主流游戏开发引擎高效集成&#xff0…

自己开发的App如何上架,详细解读App上架操作流程

对于企业或个人开发的App&#xff0c;上架是必经之路。然而&#xff0c;许多人不清楚如何进行App上架。工信部在2023年规定&#xff0c;App必须备案才能上架。那么&#xff0c;让我们一起了解App上架流程吧。 1. 准备上架所需材料 在上架App之前&#xff0c;需要准备应用图标…

如何在OceanBase v4.2 中快速生成随机数据

在使用传统数据库如 MySQL 和 Oracle 时&#xff0c;由于缺乏多样化的随机数据生成方案&#xff0c;或者实现成本过高&#xff0c;构造随机数据的开发成本受到了影响。OceanBase在老版本中虽然有相应的解决方案&#xff0c;但语法复杂和性能较差等问题仍然存在。 现在&#xf…

医学图像分割入门-UNet理论与实践

U-Net: 用于图像分割的深度学习网络 引言 在计算机视觉领域&#xff0c;图像分割是一项重要的任务&#xff0c;旨在将图像中的每个像素分配到预定义的类别或区域。传统的图像分割方法通常基于手工设计的特征和启发式算法&#xff0c;但随着深度学习的发展&#xff0c;基于深度…

负载均衡(理解/解析)

目录 什么是负载均衡 应用场景 网络服务和应用&#xff1a; 云计算和虚拟化&#xff1a; 负载均衡分类 硬件负载均衡器 软件负载均衡器 部署方式 硬件部署&#xff1a; 软件部署&#xff1a; 云部署&#xff1a; 路由模式&#xff1a; 算法实现 轮询法&#xff08;Round R…

java学习——消息队列MQ

上一篇传送门&#xff1a;点我 目前只学习了RabbitMQ&#xff0c;后续学习了其他MQ后会继续补充。 MQ有了解过吗&#xff1f;说说什么是MQ&#xff1f; MQ是Message Queue的缩写&#xff0c;也就是消息队列的意思。它是一种应用程序对应用程序的通信方法&#xff0c;使得应用…

Apache Zeppelin 命令执行漏洞复现(CVE-2024-31861)

0x01 产品简介 Apache Zeppelin 是一个让交互式数据分析变得可行的基于网页的开源框架&#xff0c;Zeppelin提供了数据分析、数据可视化等功能&#xff0c; 0x02 漏洞概述 Apache Zeppelin 中代码生成控制不当&#xff08;“代码注入”&#xff09;漏洞。攻击者可以使用 She…

Springboot集成Ehcache3实现本地缓存

如果只需要在单个应用程序中使用本地缓存&#xff0c;则可以选择Ehcache&#xff1b;它支持内存和磁盘存储&#xff0c;这里不以注解方式演示&#xff0c;通过自己实现缓存管理者灵活控制缓存的读写&#xff1b; 1、引入相关依赖 <!-- ehcache3集成start --><depende…

蓝色系UX/UI设计求职面试作品集模版figmasketchPPT可编辑源文件

页面数量: 20P 页面尺寸:1920*1080PX 交付格式&#xff1a;figma、sketch、PPT 赠送文件&#xff1a;24款高质量样机&#xff08;PSD格式&#xff09; 该作品集虽然只有20页&#xff0c;但可根据需求复制作品集里已有的页面作为模版来扩展您的设计项目 该作品集模版可编辑可修…

MySQL (索引 事务)

索引 索引是一种特殊的文件, 包含着对于数据库里所有数据的引用指针. 可以对表中的一列或多列创建索引, 并指定索引类型, 各类索引有各自的数据结构实现 索引的目的在于 快速定位, 检索数据 索引可以提高 查找 效率, 但会增加 增删改 的开销 索引创建好之后, 每次调用 查询操作…