当前位置: 首页 > news >正文

【音视频 | Ogg】libogg库详细介绍以及使用——附带libogg库解析.opus文件的C源码

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍libogg库,并给出ligogg库使用的例子🍭
😎金句分享😎:🍭子曰:不患人之不己知,患不知人也。——《论语·学而篇》。意思是,不要担心别人不了解自己,只需要担心自己不了解别人。🍭

本文未经允许,不得转发!!!

相关文章:
1、RFC3533 :Ogg封装格式版本 0(The Ogg Encapsulation Format Version 0)
2、Ogg封装格式详解——包含Ogg封装过程、数据包(packet)、页(page)、段(segment)等
3、libogg库详解介绍以及使用——附带libogg库解析.opus文件的C源码
4、RFC7845:Opus音频编解码器的Ogg封装(Ogg Encapsulation for the Opus Audio Codec)
5、opus编解码库(opus-1.4)详细介绍以及使用——附带解码示例代码
6、opus编码的Ogg封装文件详解

目录

  • 🎄一、libogg库概述
  • 🎄二、libogg库编译
    • ✨2.1 编译环境如下:
    • ✨2.2 libogg编译
  • 🎄三、libogg库简单介绍
    • ✨3.1 ogg.h 头文件
    • ✨3.2 libogg 库函数解析
  • 🎄四、Ogg封装格式使用 libogg 库解码——C语言代码
  • 🎄五、总结


在这里插入图片描述

🎄一、libogg库概述

Ogg是一种多媒体容器格式,是Xiph.org多媒体编解码器的原生文件和流格式。与所有Xiph.org技术一样,它是一种开放的格式,任何人都可以免费使用。

libogg库包含创建、解码和处理ogg比特流的必要功能。最新版本稳定版本更新到1.3.4,开发版本更新到1.3.5,libogg库的下载链接:https://xiph.org/downloads/
在这里插入图片描述

在这里插入图片描述

🎄二、libogg库编译

本文下载的是libogg-1.3.5.tar.gz

✨2.1 编译环境如下:

$ uname -a
Linux ubuntu 4.4.0-128-generic #154~14.04.1-Ubuntu SMP Fri May 25 14:58:51 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.5 LTS
Release:        14.04
Codename:       trusty$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.4' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4) 

✨2.2 libogg编译

tar zxvf libogg-1.3.5.tar.gz
cd libogg-1.3.5/
./configure --prefix=`pwd`/result_gcc
make && make install

在这里插入图片描述

🎄三、libogg库简单介绍

✨3.1 ogg.h 头文件

libogg库的所有结构体和函数都定义在 ogg.h 头文件中,并且大概分为5个部分:

  • 1、结构体;
  • 2、比特流打包函数;
  • 3、Ogg编码相关函数;
  • 4、Ogg解码相关函数;
  • 5、通用函数。

头文件内容如下:

/*********************************************************************                                                                  ** THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   ** USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     ** GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE ** IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       **                                                                  ** THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             ** by the Xiph.Org Foundation http://www.xiph.org/                  **                                                                  *********************************************************************function: toplevel libogg include********************************************************************/
#ifndef _OGG_H
#define _OGG_H#ifdef __cplusplus
extern "C" {
#endif#include <stddef.h>
#include <ogg/os_types.h>typedef struct {void *iov_base;size_t iov_len;
} ogg_iovec_t;typedef struct {long endbyte;int  endbit;unsigned char *buffer;unsigned char *ptr;long storage;
} oggpack_buffer;/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/typedef struct {unsigned char *header;long header_len;unsigned char *body;long body_len;
} ogg_page;/* ogg_stream_state contains the current encode/decode state of a logicalOgg bitstream **********************************************************/typedef struct {unsigned char   *body_data;    /* bytes from packet bodies */long    body_storage;          /* storage elements allocated */long    body_fill;             /* elements stored; fill mark */long    body_returned;         /* elements of fill returned */int     *lacing_vals;      /* The values that will go to the segment table */ogg_int64_t *granule_vals; /* granulepos values for headers. Not compactthis way, but it is simple coupled to thelacing fifo */long    lacing_storage;long    lacing_fill;long    lacing_packet;long    lacing_returned;unsigned char    header[282];      /* working space for header encode */int              header_fill;int     e_o_s;          /* set when we have buffered the last packet in thelogical bitstream */int     b_o_s;          /* set after we've written the initial pageof a logical bitstream */long    serialno;long    pageno;ogg_int64_t  packetno;  /* sequence number for decode; the framingknows where there's a hole in the data,but we need coupling so that the codec(which is in a separate abstractionlayer) also knows about the gap */ogg_int64_t   granulepos;} ogg_stream_state;/* ogg_packet is used to encapsulate the data and metadata belongingto a single raw Ogg/Vorbis packet *************************************/typedef struct {unsigned char *packet;long  bytes;long  b_o_s;long  e_o_s;ogg_int64_t  granulepos;ogg_int64_t  packetno;     /* sequence number for decode; the framingknows where there's a hole in the data,but we need coupling so that the codec(which is in a separate abstractionlayer) also knows about the gap */
} ogg_packet;typedef struct {unsigned char *data;int storage;int fill;int returned;int unsynced;int headerbytes;int bodybytes;
} ogg_sync_state;/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/extern void  oggpack_writeinit(oggpack_buffer *b);
extern int   oggpack_writecheck(oggpack_buffer *b);
extern void  oggpack_writetrunc(oggpack_buffer *b,long bits);
extern void  oggpack_writealign(oggpack_buffer *b);
extern void  oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
extern void  oggpack_reset(oggpack_buffer *b);
extern void  oggpack_writeclear(oggpack_buffer *b);
extern void  oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
extern void  oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
extern long  oggpack_look(oggpack_buffer *b,int bits);
extern long  oggpack_look1(oggpack_buffer *b);
extern void  oggpack_adv(oggpack_buffer *b,int bits);
extern void  oggpack_adv1(oggpack_buffer *b);
extern long  oggpack_read(oggpack_buffer *b,int bits);
extern long  oggpack_read1(oggpack_buffer *b);
extern long  oggpack_bytes(oggpack_buffer *b);
extern long  oggpack_bits(oggpack_buffer *b);
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);extern void  oggpackB_writeinit(oggpack_buffer *b);
extern int   oggpackB_writecheck(oggpack_buffer *b);
extern void  oggpackB_writetrunc(oggpack_buffer *b,long bits);
extern void  oggpackB_writealign(oggpack_buffer *b);
extern void  oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
extern void  oggpackB_reset(oggpack_buffer *b);
extern void  oggpackB_writeclear(oggpack_buffer *b);
extern void  oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
extern void  oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
extern long  oggpackB_look(oggpack_buffer *b,int bits);
extern long  oggpackB_look1(oggpack_buffer *b);
extern void  oggpackB_adv(oggpack_buffer *b,int bits);
extern void  oggpackB_adv1(oggpack_buffer *b);
extern long  oggpackB_read(oggpack_buffer *b,int bits);
extern long  oggpackB_read1(oggpack_buffer *b);
extern long  oggpackB_bytes(oggpack_buffer *b);
extern long  oggpackB_bits(oggpack_buffer *b);
extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);/* Ogg BITSTREAM PRIMITIVES: encoding **************************/extern int      ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
extern int      ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,int count, long e_o_s, ogg_int64_t granulepos);
extern int      ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
extern int      ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
extern int      ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
extern int      ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill);/* Ogg BITSTREAM PRIMITIVES: decoding **************************/extern int      ogg_sync_init(ogg_sync_state *oy);
extern int      ogg_sync_clear(ogg_sync_state *oy);
extern int      ogg_sync_reset(ogg_sync_state *oy);
extern int      ogg_sync_destroy(ogg_sync_state *oy);
extern int      ogg_sync_check(ogg_sync_state *oy);extern char    *ogg_sync_buffer(ogg_sync_state *oy, long size);
extern int      ogg_sync_wrote(ogg_sync_state *oy, long bytes);
extern long     ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
extern int      ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
extern int      ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
extern int      ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
extern int      ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);/* Ogg BITSTREAM PRIMITIVES: general ***************************/extern int      ogg_stream_init(ogg_stream_state *os,int serialno);
extern int      ogg_stream_clear(ogg_stream_state *os);
extern int      ogg_stream_reset(ogg_stream_state *os);
extern int      ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
extern int      ogg_stream_destroy(ogg_stream_state *os);
extern int      ogg_stream_check(ogg_stream_state *os);
extern int      ogg_stream_eos(ogg_stream_state *os);extern void     ogg_page_checksum_set(ogg_page *og);extern int      ogg_page_version(const ogg_page *og);
extern int      ogg_page_continued(const ogg_page *og);
extern int      ogg_page_bos(const ogg_page *og);
extern int      ogg_page_eos(const ogg_page *og);
extern ogg_int64_t  ogg_page_granulepos(const ogg_page *og);
extern int      ogg_page_serialno(const ogg_page *og);
extern long     ogg_page_pageno(const ogg_page *og);
extern int      ogg_page_packets(const ogg_page *og);extern void     ogg_packet_clear(ogg_packet *op);#ifdef __cplusplus
}
#endif#endif  /* _OGG_H */

✨3.2 libogg 库函数解析

下面简单介绍在Ogg封装格式解码过程中需要用到的库函数,需要了解更多库函数解释的可以参考:https://xiph.org/ogg/doc/libogg/reference.html

int      ogg_sync_init(ogg_sync_state *oy);
功能:将 ogg_sync_state *结构体 初始化为已知状态
参数:ogg_sync_state *
long     ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
功能: 将同步到比特流中的下一页,并返回关于我们前进或跳过了多少字节的信息。
返回值:-n:跳过的字节;0:页没准备好,需要更多的字节,且没跳过字节;n:页的总字节数n
char    *ogg_sync_buffer(ogg_sync_state *oy, long size);
功能:分配数据缓冲区
int      ogg_sync_wrote(ogg_sync_state *oy, long bytes);
功能:告知添加了多少字节
int      ogg_page_bos(const ogg_page *og);
功能:起始页返回1//--------------------------------------
int      ogg_page_eos(const ogg_page *og);
功能:结束页返回1//--------------------------------------
ogg_int64_t  ogg_page_granulepos(const ogg_page *og);
功能:获取页的 granule position//--------------------------------------
int      ogg_page_serialno(const ogg_page *og);
功能:获取流的序列号//--------------------------------------
long     ogg_page_pageno(const ogg_page *og);
功能:获取页的序号//--------------------------------------
int      ogg_page_packets(const ogg_page *og);
功能:获取页的的包(段segment)个数
int      ogg_stream_init(ogg_stream_state *os,int serialno);
功能:初始化ogg_stream_state结构,并分配适当的内存以准备编码或解码//--------------------------------------
int      ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
功能:将一个完整的页面添加到比特流中。//--------------------------------------
int      ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
功能:数据已经被提交到ogg_stream_state之后。每次连续调用该函数都会返回从这些数据段构建的下一个完整数据包。//--------------------------------------
int      ogg_stream_clear(ogg_stream_state *os);
功能:这个函数清除并释放ogg_stream_state结构使用的内部内存,但不释放结构本身。在同一个结构上多次调用ogg_stream_clear是安全的。

在这里插入图片描述

🎄四、Ogg封装格式使用 libogg 库解码——C语言代码

在 上篇文章 第五小节 ,笔者用C语言写了一个读取Ogg文件的测试程序,现在,这里使用ligogg库再实现一个Ogg封装格式文件读取的程序。

解码程序步骤:

  • 1、打开文件;
  • 2、调用 ogg_sync_init 初始化一个ogg_sync_state结构体;
  • 3、获取一页数据,并处理;
    • 3.1、根据序列号初始化一个比特流 ogg_stream_init
    • 3.2、把页数据给到比特流 ogg_stream_pagein
    • 3.3、获取数据包 ogg_stream_packetout
    • 3.4、释放比特流;
  • 4、关闭文件

程序使用的 48000Hz-s16le-1ch-ChengDu.opus ,是opus编码的Ogg封装文件。

程序编译需要了解前面编译好的ligogg库和头文件,参考:

gcc liboggDec.c ../../libogg-1.3.5/result_gcc/lib/libogg.a -I ../../libogg-1.3.5/result_gcc/include/

Ogg文件解码程序如下,虽然并没有完整解析出音频,但可以加深对libogg库的理解:

// ligoggDec.c
// gcc liboggDec.c ../../libogg-1.3.5/result_gcc/lib/libogg.a -I ../../libogg-1.3.5/result_gcc/include/
/*
* ogg_sync_init:将结构体初始化为已知状态* ogg_sync_pageseek: 将同步到比特流中的下一页,并返回关于我们前进或跳过了多少字节的信息。返回值:-n:跳过的字节;0:页没准备好,需要更多的字节,且没跳过字节;n:页的总字节数n* ogg_sync_buffer:分配数据缓冲区* ogg_sync_wrote:告知添加了多少字节* ogg_page_serialno:获取序列号* ogg_page_bos:起始页* ogg_page_eos:结束页* ogg_page_pageno:获取页号* ogg_page_granulepos:获取页 granule pos* ogg_page_packets:获取该页 段 (segment)个数* ogg_stream_init:初始化ogg_stream_state结构,并分配适当的内存以准备编码或解码* ogg_stream_pagein:将一个完整的页面添加到比特流中。* ogg_stream_packetout:数据已经被提交到ogg_stream_state之后。每次连续调用该函数都会返回从这些数据段构建的下一个完整数据包。* ogg_stream_clear:这个函数清除并释放ogg_stream_state结构使用的内部内存,但不释放结构本身。在同一个结构上多次调用ogg_stream_clear是安全的。
*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include "ogg/ogg.h"#define CHUNK 4096ogg_sync_state g_ogsync;
ogg_page g_page;// 获取下一页数据 2023-11-03 10:31:28
static int get_next_page(FILE *f, ogg_sync_state *ogsync, ogg_page *page,ogg_int64_t *written)
{int ret;char *buffer;size_t bytes;while((ret = ogg_sync_pageseek(ogsync, page)) <= 0) {if(ret < 0) {/* unsynced, we jump over bytes to a possible capture - we don't need to read more just yet */printf("WARNING: Hole in data (%d bytes) found at approximate offset %" PRId64 " bytes. Corrupted Ogg.\n", -ret, *written);continue;}/* zero return, we didn't have enough data to find a whole page, read */buffer = ogg_sync_buffer(ogsync, CHUNK);bytes = fread(buffer, 1, CHUNK, f);if(bytes == 0) {ogg_sync_wrote(ogsync, 0);return 0;}ogg_sync_wrote(ogsync, (long)bytes);*written += bytes;}return 1;
}int main()
{FILE *file = fopen("48000Hz-s16le-1ch-ChengDu.opus", "rb");if(!file) {printf("fopen error\n");return -1;}ogg_sync_init(&g_ogsync);ogg_int64_t written;while (get_next_page(file, &g_ogsync, &g_page, &written)){int packets = ogg_page_packets(&g_page);printf("page_num:%03lu; ",ogg_page_pageno(&g_page));printf("Oggs:%c %c %c %c; ",g_page.header[0],g_page.header[1],g_page.header[2],g_page.header[3]);printf("type=%d, granule_position:%08lld, seg_num=%d; ", g_page.header[5],(long long)ogg_page_granulepos(&g_page), packets);// 准备bit流ogg_stream_state streamState;ogg_packet packet;ogg_stream_init(&streamState, ogg_page_serialno(&g_page)); // 给定一个流序列号,初始化 streamStateogg_stream_pagein(&streamState, &g_page); // 将页数据给到 比特流int i = 0;for(i=0; i<packets; i++){ogg_stream_packetout(&streamState, &packet);if(packet.bytes >= 19 && memcmp(packet.packet, "OpusHead", 8)==0){printf("OpusHead; ");}}printf("\n");ogg_stream_clear(&streamState);}return 0;
}

Ogg编码程序,这里就不给了,需要的话,可以去看看opus-tool工具的源码。

在这里插入图片描述

🎄五、总结

本文介绍了ligogg-1.3.5库的下载、编译,以及个别库函数的用法,最后给出一个Ogg封装格式的解码程序代码。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

相关文章:

【音视频 | Ogg】libogg库详细介绍以及使用——附带libogg库解析.opus文件的C源码

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…...

如何使用群晖NAS的Audio Station结合内网穿透实现远程访问本地曲库

文章目录 本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是本教程使用环境&#xff1a;1 群晖系统安装audiostation套件2 下载移动端app3 内网穿透&#xff0c;映射至公网 很多老铁想在上班路上听点喜欢的歌或者相声解解闷儿&#xff0c;于是打开手…...

要在CentOS中安装Docker

要在CentOS中安装Docker&#xff0c;请按照以下步骤进行操作&#xff1a; 首先&#xff0c;确保系统已更新到最新版本。运行以下命令&#xff1a; sudo yum update接下来&#xff0c;安装需要的软件包以允许使用HTTPS进行软件包下载。运行以下命令&#xff1a; sudo yum ins…...

Android Gldie复用只取之前decode过的缓存resource,Kotlin

Android Gldie复用只取之前decode过的缓存resource&#xff0c;Kotlin import android.graphics.Bitmap import android.os.Bundle import android.util.Log import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.life…...

EasyExcel实现动态表头功能

EasyExcel实现动态表头功能 开发过程中&#xff0c;大部分都会使用到导出报表功能&#xff0c;目前阶段会用得有 poi导出&#xff08;暂无&#xff09;&#xff0c; easyexcel导出&#xff08;官方文档&#xff0c;https://easyexcel.opensource.alibaba.com/docs/current/&am…...

Python | 安装、环境配置及包的安装

Python | 安装、环境配置及包的安装 一、前言二、python安装及编辑器配置2.1 python安装2.2 python调试2.3 python编辑器 | PyCharm2.3.1 PyCharm下载2.3.2 PyCharm安装2.3.3 PyCharm启动界面2.3.4 PyCharm初步设置2.3.5 PyCharm环境配置(含Python Interpreter配置)2.3.5.1 New…...

CentOS 7 安装 JDK17(注意版本号要与自己的版本一致)

查看是否有自带的 JDK java -versionrpm -qa | grep jdk卸载自带 JDK rpm -e --nodeps [name] # 如 rpm -e --nodeps java-1.8.0-openjdk-1.8.0.242.b08-1.el7.x86_64查看自带 JDK 是否卸载干净 java -versionrpm -qa | grep jdk在 oracle 官网下载自己所需 JDK 版本&#x…...

JavaScript 数组操作

JavaScript 中的数组提供了各种操作方法&#xff0c;包括增加、删除、修改、查找、排序、遍历、去重和转换等。以下是一些常用的数组操作方法&#xff1a; 增加元素 push(element1, element2, …, elementN): 将一个或多个元素添加到数组的末尾&#xff0c;并返回新数组的长度…...

idea使用lombok编译问题

idea编译报错问题如下&#xff1a; java: You arent using a compiler supported by lombok, so lombok will not work and has been disabled.Your processor is: com.sun.proxy.$Proxy26Lombok supports: OpenJDK javac, ECJ解决方案&#xff1a;在idea配置中File->Setti…...

GoLong的学习之路(番外)如何使用依赖注入工具:wire

我为什么要直接写番外呢&#xff1f;其原因很简单。项目中会使用&#xff0c;其实在这里大家就可以写一些项目来了。 依赖注入的工具本质思想其实都大差不差。无非控制反转和依赖注入。 文章目录 控制反转为什么需要依赖注入工具 wire的概念提供者&#xff08;provider&#x…...

【pyspider】爬取ajax请求数据(post),如何处理python2字典的unicode编码字段?

情景&#xff1a;传统的爬虫只需要设置fetch_typejs即可&#xff0c;因为可以获取到整个页面。但是现在ajax应用越来越广泛&#xff0c;所以有的网页不能用此种爬虫类型来获取页面的数据&#xff0c;只能用slef.crawl()来发起http请求来抓取数据。 直接上例子&#xff1a; 可以…...

torch.cumprod实现累乘计算

cumprod取自“cumulative product”的缩写&#xff0c;即“累计乘法”。 数学公式为&#xff1a; y i x 1 x 2 x 3 . . . x i y_ix_1\times{x_2}\times{x_3}\times{...}\times{x_i} yi​x1​x2​x3​...xi​ 官方链接&#xff1a;torch.cumprod 用法&#xff1a; impo…...

设计模式之迭代器模式

什么是迭代器模式 迭代器模式&#xff08;Iterator pattern&#xff09;是一种对象行为型设计模式&#xff0c;它提供了一种方法来顺序访问聚合对象中的元素&#xff0c;而又不暴露该对象的内部表示&#xff0c;同时也可以将迭代逻辑与聚合对象的实现分离&#xff0c;增强了代码…...

使用SSH ,让windows和linux互通

简介 SSH 是一种安全网络协议&#xff0c;旨在让客户端和服务器之间进行安全的数据传输。SSH 的核心思想是利用公钥加密技术和共享密钥加密技术相结合的方式&#xff0c;使客户端和服务器之间建立起安全的连接。 当客户端发起连接请求时&#xff0c;服务器会对客户端进行身份验…...

常用设计模式——策略模式

策略模式是什么 策略模式&#xff08;Strategy&#xff09;&#xff1a;针对一组算法&#xff0c;将每一个算法封装起来&#xff0c;从而使得它们可以相互替换。 比如我们一个软件的会员等级&#xff0c;每一个等级都会有对应的一些等级权益&#xff0c;那么每一个等级权益就…...

牛客网 CM11.链表分割

目录 1.解题思路2.代码实现 1.解题思路 此题目思路相对简单&#xff0c;利用双指针&#xff0c;一个指针指向小于val的&#xff0c;一个指针指向大于等于val的&#xff0c;但实现起来&#xff0c;如果仅仅使用单链表&#xff0c;那么还需特别判断第一个指针是否为空从而特意做…...

[iOS开发]iOS中TabBar中间按钮凸起的实现

在日常使用app的过程中&#xff0c;经常能看到人家实现了底部分栏控制器的中间按钮凸起的效果&#xff0c;那么这是怎么实现的呢&#xff1f; 效果演示&#xff1a; 实现原理&#xff1a; 创建按钮 创建一个UITabBar的子类&#xff0c;重写它的layoutSubviews方法&#xff1…...

数字时代,企业的数据共享意味着什么?

随着数字化整体在社会方方面面的推进&#xff0c;通过数据直接或间接创造的价值越来越大&#xff0c;逐渐成为了构建现代社会的重要要素。而对于企业来说&#xff0c;数据也是在数字经济中容易接触也切实能够利用产生大量价值&#xff0c;所以如何最大化利用数据&#xff0c;让…...

壹[1],QT自定义控件创建(QtDesigner)

1&#xff0c;环境 Qt 5.14.2 VS2022 原因&#xff1a;厌烦了控件提升的繁琐设置&#xff0c;且看不到界面预览显示。 2&#xff0c;QT制作自定义控件 2.1&#xff0c;New/其他项目/Qt4 设计师自定义控件 2.2&#xff0c;设置项目名称 2.3&#xff0c;设置 2.4&#xff0c;设…...

解决Java对接LDAP AD域登录出现Unprocessed Continuation Reference(s)错误

出现该错误的原因&#xff0c;主要是因为Java namingx的库&#xff0c;默认选项是未设置跟随&#xff0c;389返回的是AD域条目的引用&#xff0c;需要进行引用跟随。 解决方法分为两种&#xff0c;第一类不使用全局目录服务的端口389和636&#xff0c;而是使用真实端口 把代码…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...