【进阶】【Python网络爬虫】【15.爬虫框架】scrapy入门(附大量案例代码)(建议收藏)

Python网络爬虫基础

  • 一、爬虫框架
    • 1. 什么是框架?
    • 2. 初期如何学习框架?
  • 二、scrapy 入门
    • 1. 网络爬虫
      • 请求数据
      • 解析数据
      • 保存数据
    • 2. scrapy安装
      • 安装方式
      • 全局命令
      • 项目命令
        • 案例 - scrapy 下厨房网爬取
          • settings.py
          • spiders
            • blood.py
        • 案例 - scrapy爬取哔哩哔哩网
          • settings.py
          • items.py
          • pipelines.py
          • iders
            • libi.py - 基于终端指令的持久化存储(简单)不推荐
            • libi,py - 基于管道的持久化存储方式(通用)
        • 案例 - scrapy数据保存到数据库
          • settings.py
          • items.py
          • pipelines.py
          • spiders
            • libi.py
        • 案例 - scrapy爬取二进制数据
          • settings.py
          • items.py
          • pipelines.py
          • spiders
            • img.py

一、爬虫框架

1. 什么是框架?

所谓的框架,其实说白了就是一个【项目的半成品】,该项目的半成品需要被集成了各种功能且具有较强的通用性。

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍。所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具有很强通用性的项目模板。对于框架的学习,重点是要学习其框架的特性、各个功能的用法即可。

2. 初期如何学习框架?

只需要学习框架集成好的各种功能的用法即可!前期切勿钻研框架的源码!

二、scrapy 入门

1. 网络爬虫

网络爬虫是指在互联网上自动爬取网站内容信息的程序,也被称作网络蜘蛛或网络机器人。大型的爬虫程序被广泛应用于搜索引擎、数据挖掘等领域,个人用户或企业也可以利用爬虫收集对自身有价值的数据。

一个网络爬虫程序的基本执行流程可以总结三个过程:请求数据解析数据保存数据

请求数据

请求的数据除了普通的HTML之外,还有 json 数据、字符串数据、图片、视频、音频等。

解析数据

当一个数据下载完成后,对数据中的内容进行分析,并提取出需要的数据,提取到的数据可以以多种形式保存起来,数据的格式有非常多种,常见的有csv、json、pickle等

保存数据

最后将数据以某种格式(CSV、JSON)写入文件中,或存储到数据库(MySQL、MongoDB)中。同时保存为一种或者多种。

  • 通常,我们想要获取的数据并不只在一个页面中,而是分布在多个页面中,这些页面彼此联系,一个页面中可能包含一个或多个到其他页面的链接,提取完当前页面中的数据后,还要把页面中的某些链接也提取出来,然后对链接页面进行爬取(循环1-3步骤)。

  • 设计爬虫程序时,还要考虑防止重复爬取相同页面(URL去重)、网页搜索策略(深度优先或广度优先等)、爬虫访问边界限定等一系列问题。

  • 从头开发一个爬虫程序是一项烦琐的工作,为了避免因制造轮子而消耗大量时间,在实际应用中我们可以选择使用一些优秀的爬虫框架,使用框架可以降低开发成本,提高程序质量,让我们能够专注于业务逻辑(爬取有价值的数据)。接下来,就带你学习目前非常流行的开源爬虫框架Scrapy

2. scrapy安装

scrapy官网: https://scrapy.org/
scrapy中文文档:https://www.osgeo.cn/scrapy/intro/overview.html

安装方式

在任意操作系统下,可以使用pip安装Scrapy,例如:

Linux/mac系统:

  • pip install scrapy(任意目录下)

Windows系统:可以直接pip install scrapy安装,如果安装出错可以采用如下方式:

  • 1.pip install wheel (任意目录下)
  • 2.下载 twisted 文件,下载网址如下: http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
  • 3.终端进入下载目录,执行 pip install Twisted-17.1.0-cp35-cp35m-win_amd64.whl
    注意:如果该步骤安装出错,则换一个版本的 whl 文件即可
  • 4.pip install pywin32 (任意目录下)

如果安装好后,在终端中录入 scrapy 指令按下回车,如果没有提示找到该指令,则表示安装成功

安装完成后我们需要测试安装是否成功,通过如下步骤确认:

  • 在 终端 中测试能否执行 scrapy 这条命令:
Scrapy 2.4.0 - no active projectUsage:scrapy <command> [options] [args]Available commands:bench				Run quick benchmark testfetch				Fetch a URL using the Scrapy downloadergenspider			 Generate new spider using pre-defined templatesrunspider			 Run a self-contained spider (without creating a project)settings			 Get settings valuesshell				Interactive scraping consolestartproject		  Create new projectversion			 Print Scrapy versionview				Open URL in browser, as seen by Scrapy[ more ]      More commands available when run from project directoryUse "scrapy <command> -h" to see more info about a command
  • 输入 scrapy bench 测试连通性,如果出现以下情况表示安装成功:

在这里插入图片描述
通过了以上两项检测,说明Scrapy安装成功了。如上所示,我们安装的是当前最新版本2.4.0。

注意:
成功安装后,在CMD下运行scrapy出现上图不算真正成功,检测真正是否成功使用scrapy bench测试,如果没有提示错误,就代表成功安装。

具体Scrapy安装流程参考:http://doc.scrapy.org/en/latest/intro/install.html##intro-install-platform-notes 里面有各个平台的安装方法

全局命令

Scrapy 2.4.0 - no active projectUsage:scrapy <command> [options] [args]Available commands:bench				Run quick benchmark test# 测试电脑性能fetch				Fetch a URL using the Scrapy downloader# 将源代码下载下来并显示出来genspider			 Generate new spider using pre-defined templates# 创建一个新的 spider 文件runspider			 Run a self-contained spider (without creating a project)# 这个和通过crawl启动爬虫不同,scrapy runspider 爬虫文件名称settings			 Get settings values# 获取当前的配置信息shell				Interactive scraping console# 进入 scrapy 的交互模式startproject		  Create new project# 创建爬虫项目version			 Print Scrapy version# 显示scrapy框架的版本view				Open URL in browser, as seen by Scrapy# 将网页document内容下载下来,并且在浏览器显示出来[ more ]      More commands available when run from project directoryUse "scrapy <command> -h" to see more info about a command

项目命令

  • scrapy startproject projectname项目名称
## 创建一个项目
firstBlood   # 项目所在文件夹, 建议用pycharm打开该文件夹├── firstBlood  		# 项目跟目录│   ├── __init__.py│   ├── items.py  		# 封装数据的格式│   ├── middlewares.py  # 所有中间件│   ├── pipelines.py	# 所有的管道│   ├── settings.py		# 爬虫配置信息│   └── spiders			# 爬虫文件夹, 稍后里面会写入爬虫代码│       └── __init__.py└── scrapy.cfg			# scrapy项目配置信息,不要删它,别动它,善待它. 
  • cd project_name(进入项目目录)

  • scrapy genspider 爬虫文件的名称 (自定义一个名字即可) 起始url (随便写一个网址即可)

    创建好爬虫项目以后,还需要创建爬虫。

  • scrapy crawl spidername

    运行爬虫。注意该命令运行时所在的目录

案例 - scrapy 下厨房网爬取
settings.py
BOT_NAME = "First"SPIDER_MODULES = ["First.spiders"]
NEWSPIDER_MODULE = "First.spiders"
# 指定输出的日志类型
LOG_LEVEL = 'ERROR'# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"# Obey robots.txt rules
ROBOTSTXT_OBEY = FalseREQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
FEED_EXPORT_ENCODING = "utf-8"
spiders
blood.py
import scrapyclass BloodSpider(scrapy.Spider):# 爬虫文件的唯一标识name = "blood"# 允许的域名allowed_domains = ["www.baidu.com"]# 起始的 url 列表(重要):列表内部的 url 都会被框架进行异步的请求发送start_urls = ["https://www.xiachufang.com/category/40076/"]# 数据解析 : parse 调用的次数取决于 start_urls 列表元素的个数def parse(self, response):  # response 参数就表示响应对象# 如何实现数据解析 : Xpathli_list = response.xpath('/html/body/div[4]/div/div/div[1]/div[1]/div/div[2]/div[2]/ul/li')for li in li_list:# xpath 最终会返回的是 Selector 对象,想要的解析的数据是存储在该对象的 data 属性中(extract可以实现该功能)# title = li.xpath('./div/div/p[1]/a/text()')[0].extract()  # 一般不用# extract_first 可以将 xpath 返回类别中的第一个 Selector 对象中的 data 属性值获取# title = li.xpath('./div/div/p[1]/a/text()').extract_first()# extract 可以将 xpath 返回列表中的每一个 Selector 对象中的 data 属性值获取title = li.xpath('./div/div/p[1]/a/text()').extract()# 如果 xpath 返回的列表元素只有一个则使用 extract_first ,否则使用 extractprint(title)
案例 - scrapy爬取哔哩哔哩网
settings.py
BOT_NAME = "biliPro"SPIDER_MODULES = ["biliPro.spiders"]
NEWSPIDER_MODULE = "biliPro.spiders"# 指定输出的日志类型
LOG_LEVEL = 'ERROR'# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"# Obey robots.txt rules
ROBOTSTXT_OBEY = FalseREQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
FEED_EXPORT_ENCODING = "utf-8"
items.py
import scrapyclass BiliproItem(scrapy.Item):title = scrapy.Field()author = scrapy.Field()
pipelines.py
# 存储 txt 文件
class BiliproPipeline:# 一个管道类只负责将数据存储到一个载体中fp = None# 全程只会被调用一次def open_spider(self, spider):print('i am open_spider()')self.fp = open('bili.txt', 'w')# process_item 函数就是用来接受爬虫文件提交过来的item对象,且可以将item对象中的数据存储到任何载体中def process_item(self, item, spider):  # 参数 item 就是管道接收到item对象title = item['title']author = item['author']# 数据存储到文件里self.fp.write(author + ':' + title + '\n')return item# process_item 函数调用的次数取决于爬虫文件给管道提交的 item 的次数def close_spider(self, spider):print('i am close_spider()')# 该函数只会在爬虫结束前被调用一次self.fp.close()
iders
libi.py - 基于终端指令的持久化存储(简单)不推荐
import scrapyclass LibiSpider(scrapy.Spider):name = "libi"allowed_domains = ["www.xxx.com"]start_urls = ["https://search.bilibili.com/all?keyword=%E5%AE%8F%E8%A7%82%E7%BB%8F%E6%B5%8E&from_source=webtop_search&spm_id_from=333.1007&search_source=5"]# 基于终端指令的持久化存储(简单):只可以将 parse 方法的返回值存储写入到指定后缀的文本文件中def parse(self, response):div_list = response.xpath('//*[@id="i_cecream"]/div/div[2]/div[2]/div/div/div/div[3]/div/div')all_data = []for div in div_list:title = div.xpath('./div/div[2]/div/div/a/h3/text()').extract()title = ''.join(title)author = div.xpath('./div/div[2]/div/div/p/a/span[1]/text()').extract_first()dic = {'title': title,'author': author,}all_data.append(dic)return all_data  # all_data里面就存储了爬取到的数据# 指令 scrapy crawl bili -o bili.csv
libi,py - 基于管道的持久化存储方式(通用)
import scrapyfrom ..items import BiliproItemclass LibiSpider(scrapy.Spider):name = "libi"allowed_domains = ["www.xxx.com"]start_urls = ["https://search.bilibili.com/all?keyword=%E5%AE%8F%E8%A7%82%E7%BB%8F%E6%B5%8E&from_source=webtop_search&spm_id_from=333.1007&search_source=5"]# 基于管道的持久化存储方式(通用)def parse(self, response):div_list = response.xpath('//*[@id="i_cecream"]/div/div[2]/div[2]/div/div/div/div[3]/div/div')all_data = []for div in div_list:title = div.xpath('./div/div[2]/div/div/a/h3/text()').extract()title = ''.join(title)author = div.xpath('./div/div[2]/div/div/p/a/span[1]/text()').extract_first()# 创建一个 item 类型的对象item = BiliproItem(title=title, author=author)yield item# 编码流程:1.解析数据 2.创建一个 item 类的对象(存储解析出来的数据)3.将解析出来的数据存储到该 item 类型的对象中 4.将item对象提交给管道# 爬虫文件:libi.py  进行请求发送和数据解析# item文件: items.py  定义n个变量# 管道文件: pipelines.py  接收item对象进行数据持久化存储
案例 - scrapy数据保存到数据库
  • 如何将数据存储到数据库
    • 注意:一个管道类负责将数据存储到一个具体的载体中。如果想要将爬取到的数据存储到多个不同的载体/数据库中,则需要定义多个管道类。
  • 思考:
    • 在有多个管道类的前提下,爬虫文件提交的item会同时给每一个管道类还是单独的管道类?
      • 爬虫文件只会将item提交给优先级最高的那一个管道类。优先级最高的管道类的process_item中需要写return item操作,该操作就是表示将item对象传递给下一个管道类,下一个管道类获取了item对象,才可以将数据存储成功!
settings.py
BOT_NAME = "biliPro"
SPIDER_MODULES = ["biliPro.spiders"]
NEWSPIDER_MODULE = "biliPro.spiders"# 指定输出的日志类型
LOG_LEVEL = 'ERROR'USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"# Obey robots.txt rules
ROBOTSTXT_OBEY = FalseITEM_PIPELINES = {# value 值表示的数字代表了管道类的优先级,数字越小表示优先级越高"biliPro.pipelines.BiliproPipeline": 300,"biliPro.pipelines.MysqlPipeline": 301,"biliPro.pipelines.RedisPipeLine": 302,"biliPro.pipelines.MongoPipeline": 303,
}REQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
FEED_EXPORT_ENCODING = "utf-8"
items.py
import scrapyclass BiliproItem(scrapy.Item):title = scrapy.Field()author = scrapy.Field()
pipelines.py
import pymysql  # pip install pymysql''' 第一个管道类:存储 txt 文件 '''
class BiliproPipeline:  # 一个管道类只负责将数据存储到一个载体中fp = None# 全程只会被调用一次def open_spider(self, spider):print('i am open_spider()')self.fp = open('bili.txt', 'w')# process_item 函数就是用来接受爬虫文件提交过来的item对象,且可以将item对象中的数据存储到任何载体中def process_item(self, item, spider):  # 参数 item 就是管道接收到item对象title = item['title']author = item['author']# 数据存储到文件里self.fp.write(author + ':' + title + '\n')return item# process_item 函数调用的次数取决于爬虫文件给管道提交的 item 的次数def close_spider(self, spider):print('i am close_spider()')# 该函数只会在爬虫结束前被调用一次self.fp.close()''' 第二个管道类:存储到 mysql 数据库 '''
class MysqlPipeline:conn = None  # 链接对象cursor = None  # 游标对象def open_spider(self, spider):# 链接数据库的操作只需要被执行一次self.conn = pymysql.Connect(host='127.0.0.1',  # mysql 数据库服务器的ip地址port=3306,  # 端口号user='root',  # 用户名password='root',  # 密码db='spider',  # 数据仓库名称)# 创建一个游标对象(用来使用python程序执行sql语句)self.cursor = self.conn.cursor()def process_item(self, item, spider):  # 参数 item 就是管道接收到item对象,由上级优先级高的管道类传递过来title = item['title']author = item['author']# 使用游标对象 cursor 执行 sql语句sql = 'insert into bili values ("%s","%s")' % (title, author)self.cursor.execute(sql)# 提交事物self.conn.commit()return itemdef close_spider(self, spider):self.conn.close()self.cursor.close()''' 第三个管道类:存储 Redis 数据库 '''
class RedisPipeLine:conn = Nonedef open_spider(self, spider):# 创建 redis 的链接对象self.conn = Redis(host='127.0.0.1',port=3308)def process_item(self, item, spider):  # 参数 item 就是管道接收到item对象,由上级优先级高的管道类传递过来# item 本身就是一个字典self.conn.lpush('libi', item)return itemdef close_spider(self, spider):pass''' 第四个管道类:存储 MongoDB 数据库 '''
import pymongo
class MongoPipeline:conn = None  # 链接对象db_sanqi = None  # 数据仓库def open_spider(self, spider):self.conn = pymongo.MongoClient(host='127.0.0.1',port=27017)self.db_sanqi = self.conn['sanqi']def process_item(self, item, spider):self.db_sanqi['xiaoshuo'].insert_one({'title': item['title']})print('插入成功!')return item
spiders
libi.py
import scrapyfrom ..items import BiliproItemclass LibiSpider(scrapy.Spider):name = "libi"allowed_domains = ["www.xxx.com"]start_urls = ["https://search.bilibili.com/all?keyword=%E5%AE%8F%E8%A7%82%E7%BB%8F%E6%B5%8E&from_source=webtop_search&spm_id_from=333.1007&search_source=5"]# 基于管道的持久化存储方式(通用)def parse(self, response):div_list = response.xpath('//*[@id="i_cecream"]/div/div[2]/div[2]/div/div/div/div[3]/div/div')all_data = []for div in div_list:title = div.xpath('./div/div[2]/div/div/a/h3/text()').extract()title = ''.join(title)author = div.xpath('./div/div[2]/div/div/p/a/span[1]/text()').extract_first()# 创建一个 item 类型的对象item = BiliproItem(title=title, author=author)yield item  # item会提交给那个管道类?一定是提交给优先级最高的管道类!!# 编码流程:1.解析数据 2.创建一个 item 类的对象(存储解析出来的数据)3.将解析出来的数据存储到该 item 类型的对象中 4.将item对象提交给管道# 爬虫文件:libi.py  进行请求发送和数据解析# item文件: items.py  定义n个变量# 管道文件: pipelines.py  接收item对象进行数据持久化存储
  1. 在爬虫文件中进行数据爬取和数据解析
  2. 在 items.py 文件中进行相关变量的定义(变量的个数取决于爬虫文件中解析字段的个数)
  3. 在爬虫文件中将解析到的数据存储到item类型的对象中
  4. 将 item 类型的对象提交给管道
  5. 管道的 process_item 函数中接收item对象,且将 item 对象的数据存储到指定的平台或者载体中
  6. 在配置文件中开启管道的机制
案例 - scrapy爬取二进制数据

使用一个专有的管道类ImagesPipeline

  • http://pic.netbian.com/4kmeinv/

首先安装插件 : pip install PIL / pip install Pillow

  • 具体的编码流程:
    • 1.在爬虫文件中进行图片/视频的链接提取
    • 2.将提取到的链接封装到items对象中,提交给管道
    • 3.在管道文件中自定义一个父类为ImagesPipeline的管道类,且重写三个方法即可:
def get_media_requests(self, item, info):接收爬虫文件提交过来的item对象,然后对图片地址发起网路请求,返回图片的二进制数据def file_path(self, request, response=None, info=None, *, item=None):指定保存图片的名称
def item_completed(self, results, item, info):返回item对象给下一个管道类
settings.py
BOT_NAME = "imgPro"SPIDER_MODULES = ["imgPro.spiders"]
NEWSPIDER_MODULE = "imgPro.spiders"# 指定输出的日志类型
LOG_LEVEL = 'ERROR'# Obey robots.txt rules
ROBOTSTXT_OBEY = False
IMAGES_STORE = 'girlsLib'ITEM_PIPELINES = {"imgPro.pipelines.BytesPipeLine": 300,
}REQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
FEED_EXPORT_ENCODING = "utf-8"
items.py
import scrapyclass ImgproItem(scrapy.Item):img_src = scrapy.Field()
pipelines.py
import scrapy
from scrapy.pipelines.images import ImagesPipeline# 普通的管道类:将文本数据持久化
class ImgproPipeline:def process_item(self, item, spider):return item# 特殊的管道类:将二进制数据持久化
# 自定义了一个管道类,该类的父类为 ImagesPipeline
class BytesPipeLine(ImagesPipeline):# 重写三个父类的方法来完成图片二进制数据的请求和持久化存储# 可以根据图片地址,对其进行请求,获取图片数据# 接收爬虫文件提交过来的item对象,并且可以对相关的多媒体资源进行网络请求def get_media_requests(self, item, info):# 提取图片地址或者视频地址img_src = item['img_src']# 可以对 img_src 进行网络请求获取图片数据yield scrapy.Request(img_src)def file_path(self, request, response=None, info=None, *, item=None):  # 指定保存图片的名称# 用来将请求到的多媒体数据进行指定路径的存储# 返回存储文件的名字img_src = request.url  # 图片地址img_title = img_src.split('/')[-1]print(img_title, '下载保存成功!')return img_title# 如果没有下一个管道类,该方法可以不写def item_completed(self, results, item, info):  # 返回item对象给下一个管道类return item  # 可以将当前的管道类接收到item对象传递给下一个管道类2.
spiders
img.py
import scrapy
from ..items import ImgproItemclass ImgSpider(scrapy.Spider):name = "img"# allowed_domains = ["www.xxx.com"]start_urls = ["http://pic.netbian.com/4kmeinv/"]def parse(self, response):# 解析图片地址li_list = response.xpath('//*[@id="main"]/div[3]/ul/li')for li in li_list:img_src = 'http://pic.netbian.com' + li.xpath('./a/img/@src').extract_first()# 图片地址封装到item对象中,且将item提交给管道即可item = ImgproItem(img_src=img_src)print(item)yield item# 特殊的管道类:主要是对二进制的数据进行持久化存储

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高可用解决方案 Keepalived 概述

概述 Keepalived 介绍 Keepalived 是 Linux 下一个轻量级别的高可用解决方案&#xff0c;通过 **VRRP 协议&#xff08;虚拟路由冗余协议&#xff09;**来实现服务或者网络的高可用&#xff0c;可以利用其来解决单点故障。 起初是为 LVS 设计的&#xff0c;一个 LVS 服务会有 …

【中小型企业网络实战案例 五】配置可靠性和负载分担

【中小型企业网络实战案例 三】配置DHCP动态分配地址-CSDN博客 【中小型企业网络实战案例 四】配置OSPF动态路由协议 【中小型企业网络实战案例 二】配置网络互连互通-CSDN博客 【中小型企业网络实战案例 一】规划、需求和基本配置_大小企业网络配置实例-CSDN博客 配置VRRP联…

【Python】配置环境变量

Python配置Windows系统环境变量 打开电脑属性 ——> 高级系统设置 ——> 高级 ——> 环境变量 Python安装目录 D:\Program Files\Python39 winR打开运行&#xff0c;输入cmd打开命令窗口 python -V

MyBatis分页机制深度解析

前言 在企业项目的数据库操作中&#xff0c;分页查询是一个常见需求&#xff0c;尤其当数据量庞大时。MyBatis 作为 我们Java 开发者的持久层框架&#xff0c;为分页提供了灵活的支持。 本篇文章我们将深入探讨 MyBatis 的分页机制&#xff0c;使我们在实际开发项目中运用自如…

Nginx解决跨域问题过程

学习Nginx解决跨域问题 结果 server {listen 22222;server_name localhost;location / {if ($request_method OPTIONS) {add_header Access-Control-Allow-Origin http://localhost:8080;add_header Access-Control-Allow-Headers *;add_header Access-Control-Allo…

【索引的数据结构】第2章节:InooDB和MyISAM索引结构对比

目录结构 之前整篇文章太长&#xff0c;阅读体验不好&#xff0c;将其拆分为几个子篇章。 本篇章讲解 InnoDB 和 MyISAM 索引结构对比。 InnoDB 的 BTree 索引注意事项 根页面位置万年不变 上述我们在索引迭代的过程中&#xff0c;为了更佳形象的描述&#xff0c;所以将顺序…

【图像拼接】源码精读:Seam-guided local alignment and stitching for large parallax images

第一次来请先看这篇文章&#xff1a;【图像拼接&#xff08;Image Stitching&#xff09;】关于【图像拼接论文源码精读】专栏的相关说明&#xff0c;包含专栏内文章结构说明、源码阅读顺序、培养代码能力、如何创新等&#xff08;不定期更新&#xff09; 【图像拼接论文源码精…

openGauss Summit 2023 GBase 8c多模多态、向量加持

2023年12月28日&#xff0c;以“汇聚数据库创新力量&#xff0c;打造千行万业数据基石”为主题的openGauss Summit 2023峰会于北京望京凯悦酒店顺利落幕。GBASE南大通用携重大升级的GBase 8c数据库产品及行业解决方案亮相本届大会。 关于openGauss summit峰会 openGauss Summi…

python实现Ethernet/IP协议的客户端(三)

Ethernet/IP是一种工业自动化领域中常用的网络通信协议&#xff0c;它是基于标准以太网技术的应用层协议。作为工业领域的通信协议之一&#xff0c;Ethernet/IP 提供了一种在工业自动化设备之间实现通信和数据交换的标准化方法。python要实现Ethernet/IP的客户端&#xff0c;可…

Android 13 - Media框架(29)- MediaCodec(四)

上一节我们了解了如何通过 onInputBufferAvailable 和 getInputBuffer 获取到 input buffer index&#xff0c;接下来我们一起学习上层如何拿到buffer并且向下写数据的。 1、获取 input Buffer 获取 MediaCodec 中的 buffer 有两种方式&#xff0c;一种是调用 getInputBuffers…

JavaWeb——前端之HTMLCSS

学习视频链接&#xff1a;https://www.bilibili.com/video/BV1m84y1w7Tb/?spm_id_from333.999.0.0 一、Web开发 1. 概述 能通过浏览器访问的网站 2. Web网站的开发模式——主流是前后端分离 二、前端Web开发 1. 初识 前端编写的代码通过浏览器进行解析和渲染得到我们看到…

JMeter之测试WebService接口

JMeter之测试WebService接口 1 背景2 目的3 介绍4 具体操作4.1 soapUI调用4.2 JMeter工具调用4.3 操作步骤流程4.3 重点 1 背景 WebService应用的范围是非常广&#xff0c;任何需要跨平台、跨系统进行数据交换和功能调用的场景都可以用此来实现&#xff0c;在实际的工作中也常常…