ps文件解析(純c解析代碼)

来源:https://www.cnblogs.com/leaffei/archive/2019/03/07/10487540.html
-Advertisement-
Play Games

參考鏈接:1. PS流的格式和解析總結 http://www.cnblogs.com/lihaiping/p/4181607.html 2. TS科普5 PES包解析 https://blog.csdn.net/cabbage2008/article/details/49612011 PES包的解析 ...


參考鏈接:1. PS流的格式和解析總結 http://www.cnblogs.com/lihaiping/p/4181607.html
     2. TS科普5 PES包解析 https://blog.csdn.net/cabbage2008/article/details/49612011

PES包的解析(本代碼主要解析了PTS和DTS, 需結合下圖和代碼中的PES包的偽代碼看):

startcode(24) + streamid(8) + pes_len(16) + {header: flag1(8) + flag2(8, pts標識在這兒) + header_len(8)} + {header_data(header_len, 若前面的flag有數據, 數據就在這兒)} + pes_data(pes_len-3-header_len)

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <arpa/inet.h>
  5 
  6 #define TAB44 "    "
  7 #define PRINTF_DEBUG
  8 
  9 #define MAX_PS_STARTCODE_LEN 4
 10 #define MAX_PDTS_LEN 5
 11 #define MAX_ES_NUMS 6
 12 #define MAX_PDTS_STRING_LEN 12
 13 #define MMIN_PS_HEADER_LEN 14
 14 
 15 
 16 #define SCODE_PS_END 0x000001B9
 17 #define SCODE_PS_HEADER 0x000001BA
 18 #define SCODE_PS_SYSTEM_HEADER 0x000001BB
 19 #define SCODE_PS_SYSTEM_MAP_HEADER 0x000001BC
 20 
 21 /**********************************************************************************************************
 22 pack_header() {
 23     pack_start_code                                        32 bits
 24     '01'                                                2 bits
 25     system_clock_reference_base[32..30]                    3 bits
 26     marker_bit                                            1 bit
 27     system_clock_reference_base[29..15]                    15 bits
 28     marker_bit                                            1 bit
 29     system_clock_reference_base[14..0]                    15 bits
 30     marker_bit                                            1 bit
 31     system_clock_reference_extension                    9 bits
 32     marker_bit                                            1 bit
 33     program_mux_rate                                    22 bits
 34     marker_bit                                            1 bit
 35     marker_bit                                            1 bit
 36     reserved                                            5 bit
 37     pack_stuffing_length                                3 bits
 38 
 39     for (i=0; i<pack_stuffing_length; i++){
 40         stuffing_byte                                    8 bits
 41     }
 42 
 43     if (nextbits() == system_header_start_code) {
 44         system_header()
 45     }
 46 }
 47 **********************************************************************************************************/
 48 
 49 
 50 /**********************************************************************************************************
 51 system_header() {
 52     system_header_start_code                            32 bits
 53     header_length                                        16 bits
 54     marker_bit                                            1 bit
 55     rate_bound                                            22 bits
 56     marker_bit                                            1 bit
 57     audio_bound                                            6 bits
 58     fixed_flag                                            1 bit
 59     CSPS_flag                                            1 bit
 60     system_audio_lock_flag                                1 bit
 61     system_video_lock_flag                                1 bit
 62     marker_bit                                            1 bit
 63     vedio_bound                                            5 bits
 64     packet_rate_restriction_flag                        1 bit
 65     reserved_bits                                        7 bits
 66 
 67     while (nextbits() == '1') {
 68         stream_id                                        8 bits
 69         '11'                                            2 bits
 70         P-STD_buffer_bound_scale                        1 bit
 71         P-STD_buffer_size_bound                            13 bits
 72     }
 73 }
 74 **********************************************************************************************************/
 75 
 76 
 77 /**********************************************************************************************************
 78 program_stream_map() {
 79     packet_start_code_prefix             24 bits
 80     map_stream_id                        8 bits
 81     program_stream_map_length            16 bits
 82     current_next_indicator                1 bit
 83     reserved                            2 bits
 84     program_stream_map_version            5 bits
 85     reserved                            7 bits
 86     marker_bit                            1 bit
 87     program_stream_info_length            16 bits
 88 
 89     for (i=0;i<N;i++) {
 90         descriptor()
 91     }
 92 
 93     elementary_stream_map_length        16 bits
 94 
 95     for (i=0;i<N1;i++) {
 96        stream_type                        8 bits
 97        elementary_stream_id                8 bits
 98 
 99        elementary_stream_info_length    16 bits
100 
101        for (i=0;i<N2;i++) {
102            descriptor()
103        }
104     }
105 
106     CRC_32                                32 bits
107 }
108 
109 ** current_next_indicator: 當前下一個指示符欄位, 1位欄位. 置'1'時表示傳送的節目流映射當前是可用的.
110         置'0'時表示傳送的節目流映射還不可用, 但它將是下一個生效的表.
111 ** program_stream_map_version: 5位欄位, 表示整個節目流映射的版本號. 一旦節目流映射的定義發生變化,
112         該欄位將遞增1, 並對32取模. 在current_next_indicator為'1'時, 該欄位應該是當前適用的節目流映射的版本號;
113         在current_next_indicator為'0'時, 該欄位應該是下一個適用的節目流映射的版本號.
114 ** stream_type: 流類型欄位, 該欄位只能標誌包含在PES分組中的基本流且取值不能為0x05.
115                 1. MPEG-4視頻流: 0x10;
116                 2. H.264視頻流: 0x1B;
117                 3. SVAC視頻流: 0x80;
118                 4. G.711音頻流: 0x90;
119                 5. G.722.1音頻流: 0x92;
120                 6. G.723.1音頻流: 0x93;
121                 7. G.729音頻流: 0x99;
122                 8. SVAC音頻流: 0x9B.
123         因為節目映射流欄位只有在關鍵幀打包的時候, 才會存在, 所以如果要判斷PS打包的流編碼類型, 就根據這個欄位來判斷.
124 ** elementary_stream_map_length: 基本流映射長度欄位. 指出在該節目流映射中的所有基本流信息的位元組長度.
125         它只包括stream_type、elementary_stream_id和elementary_stream_info_length欄位.
126 ** elementary_stream_id: 基本流標識欄位, 8位欄位, 指出該基本流所在PES分組的PES分組標題中stream_id欄位的值.
127         這個欄位的定義, 其中0x(C0~DF)指音頻, 0x(E0~EF)為視頻.
128 **********************************************************************************************************/
129 typedef struct t_es_map
130 {
131     unsigned char streamType;
132     unsigned char esId;
133     unsigned short esInfoLen;
134 } T_ES_MAP;
135 
136 typedef struct t_ps_map 
137 {
138     unsigned char curNextInd:1, :2, version:5;
139     
140     unsigned short psInfoLen;
141     unsigned short esStreamMapLen;
142     
143     unsigned int esMapNum;
144     
145     T_ES_MAP esMaps[MAX_ES_NUMS];
146 } T_PS_MAP;
147 
148 /**********************************************************************************************************
149 PES_packet() {
150     packet_start_code_prefix                                24 bits
151     stream_id                                                8 bits
152     PES_packet_length                                        16 bits
153 
154     if (stream_id != program_stream_map 
155         && stream_id != padding_stream
156         && stream_id != private_stream_2
157         && stream_id != ECM
158         && stream_id != EMM
159         && stream_id != program_stream_directory
160         && stream_id !=    DSMCC_stream
161         && stream_id != ITU-T Rec.H.222.1 type E stream) {
162             '10'                                            2 bits
163             PES_scrambling_control                            2 bits
164             PES_priority                                    1 bit
165             data_alignment_indicator                        1 bit
166             copyright                                        1 bit
167             original_or_copy                                1 bit
168             
169             PTS_DTS_flags                                    2 bits
170             ESCR_flag                                        1 bit
171             ES_rate_flag                                    1 bit
172             DSM_trick_mode_flag                                1 bit
173             additional_copy_info_flag                        1 bit
174             PES_CRC_flag                                    1 bit
175             PES_extension_flag                                1 bit
176             
177             PES_header_data_length                            8 bits
178 
179             if (PTS_DTS_flags == '10') {
180                 '0010'                                        4 bits
181                 PTS[32..30]                                    3 bits
182                 marker_bit                                    1 bit
183                 PTS[29..15]                                    15 bits
184                 marker_bit                                    1 bit
185                 PTS[14..0]                                    15 bits
186                 marker_bit                                    1 bit
187             }
188             
189             if (PTS_DTS_flags == '11') {
190                 '0011'                                        4 bits
191                 PTS[32..30]                                    3 bits
192                 marker_bit                                    1 bit
193                 PTS[29..15]                                    15 bits
194                 marker_bit                                    1 bit
195                 PTS[14..0]                                    15 bits
196                 marker_bit                                    1 bit
197                 '0001'                                        4 bits
198                 PTS[32..30]                                    3 bits
199                 marker_bit                                    1 bit
200                 PTS[29..15]                                    15 bits
201                 marker_bit                                    1 bits
202                 PTS[14..0]                                    15 bits
203                 marker_bit                                    1 bit
204             }
205 
206             if (ESCR_flag == '1') {
207                 reserved                                    2 bits
208                 ESCR_base[32..30]                            3 bits
209                 marker_bit                                    1 bit
210                 ESCR_base[29..15]                            15 bits
211                 marker_bit                                    1 bit
212                 ESCR_base[14..0]                            15 bits
213                 marker_bit                                    1 bit
214                 ESCR_extension                                9 bits
215                 marker_bit                                    1 bit
216             }
217 
218             if (ES_rate_flag == '1') {
219                 marker_bit                                    1 bit
220                 ES_rate                                        22 bits
221                 marker_bit                                    1 bit
222             }
223 
224             if (DSM_trick_mode_flag == '1') {
225                 trick_mode_control                            3 bits
226 
227                 if (trick_mode_control == fast_forward) {
228                     field_id                                2 bits
229                     intra_slice_refresh                        1 bits
230                     frequency_truncation                    2 bits
231                 } else if (trick_mode_control == slow_motion) {
232                     rep_cntrl                                5 bits
233                 } else if (trick_mode _control == freeze_frame) {
234                     field_id                                2 bits
235                     reserved                                3 bits
236                 } else if (trick_mode _control == fast_reverse) {
237                     field_id                                2 bits
238                     intra_slice_refresh                        1 bit
239                     frequency_truncation                    2 bits
240                 } else if (trick_mode_control == slow_reverse) {
241                     rep_cntrl                                5 bits
242                 } else {
243                     reserved                                5 bits
244                 }
245             }
246 
247             if (additional_copy_info_flag =='1') {
248                 marker_bit                                    1 bit
249                 additional_copy_info                        7 bits
250             }
251 
252             if (PES_CRC_flag == ‘1’) {
253                 previous_PES_packet_CRC                        16 bits
254             }
255 
256             if (PES_extension_flag == '1') {
257                 PES_private_data_flag                        1 bit
258                 pack_header_field_flag                        1 bit
259                 program_packet_sequence_counter_flag        1 bit
260                 P-STD_buffer_flag                            1 bit
261                 reserved                                    3 bits
262                 PES_extension_flag_2                        1 bit
263 
264                 if (PES_private_data_flag == '1') {
265                     PES_private_data                        128 bits
266                 }
267 
268                 if (pack_header_field_flag == '1') {
269                     pack_field_length                        8 bits
270                     pack_header()
271                 }
272 
273                 if (program_packet_sequence_counter_flag == '1') {
274                     marker_bit                                1 bit
275                     program_packet_sequence_counter            7 bits
276                     marker-bit                                1 bit
277                     MPEG1_MPEG2_indentifier                    1 bit
278                     original_stuff_length                    6 bits
279                 }
280 
281                 if (P-STD_buffer_flag == '1') {
282                     '01'                                    2 bits
283                     P-STD_buffer_scale                        1 bit
284                     P-STD_buffer_size                        13 bits
285                 }
286 
287                 if (PES_extension_flag_2 == '1') {
288                     marker_bit                                1 bit
289                     PES_extension_field_length                7 bits
290 
291                     for (i=0; i<PES_extension_field_length; i++) {
292                         reserved                            8 bits
293                     }
294                 }
295             }
296 
297             for (i=0; i<N1; i++) {
298                 stuffing_byte                                    8 bits
299             }
300             
301             for (i=0; i<N2; i++) {
302                 PES_packet_data_byte                            8 bits
303             }
304     } else if (stream_id == program_stream_map
305                 || stream_id == private_stream_2
306                 || stream_id == ECM
307                 || stream_id == EMM
308                 || stream_id == program_stream_directory
309                 || stream_id == DSMCC_stream
310                 || stream_id == ITU-T Rec. H.222.1 type E stream ) {
311                     for (i=0; i<PES_packet_length; i++) {
312                         PES_packet_data_byte                    8 bits
313                     }
314     } else if (steam_id == padding_stream) {
315         for (i=0; i<PES_packet_length; i++) {
316             padding_byte                                        8 bits
317         }
318     }
319 }
320 
321 ** stream_id:
322         1011 1100        program_stream_map(0xBC)
323         1011 1101        private_stream_1(0xBD)
324         1011 1110        padding_stream(0xBE)
325         1011 1111        private_stream-2(0xBF)
326         110x xxxx        GB/T XXXX.3或GB/T AAAA.3音頻流編號xxxx(0xC0~0xDF)
327         1110 xxxx        GB/T XXXX.2或GB/T AAAA.2視頻流編號xxxx(0xE0~0xEF)
328         1111 0000        ECM_stream(0xF0)
329         1111 0001        EMM_stream(0xF1)
330         1111 0010        GB/T XXXX.1附錄B或GB/T XXXX.6_DSMCC_stream(0xF2)
331         1111 0011        ISO/IEC_13522_stream(0xF3)
332         1111 0100        ITU-T Rec. H.222.1類型A
333         1111 0101        ITU-T Rec. H.222.1類型B
334         1111 0110        ITU-T Rec. H.222.1類型C
335         1111 0111        ITU-T Rec. H.222.1類型D
336         1111 1000        ITU-T Rec. H.222.1類型E
337         1111 1001        ancillary_stream(0xF9)
338         1111 1010…1111 1110        保留數據流
339         1111 1111        program_stream_directory(0xFF)
340         符號x表示值'0'或'1'均被允許且可產生相同的流類型. 流號碼由x的取值決定.
341 **********************************************************************************************************/
342 typedef struct t_ps_pes
343 {
344     unsigned char streamId;
345     
346     long long pts;
347     long long dts;
348     
349     unsigned char ptsStr[MAX_PDTS_STRING_LEN+1];
350     unsigned char dtsStr[MAX_PDTS_STRING_LEN+1];
351     
352     unsigned char pesHeaderLen;
353 } T_PS_PES;
354 
355 static void parsePsHeader(unsigned char* const psHeaderData)
356 {
357     
358 }
359 
360 static void parsePsSystemHeader(unsigned char* const psSysHeaderData)
361 {
362 
363 }
364 
365 static void parsePsSystemMapHeader(unsigned char* const psMapHeaderData)
366 {
367     int i = 0;
368     
369     T_PS_MAP psMap = {0};
370     
371     unsigned char *data = NULL;
372     
373     data = psMapHeaderData;
374     
375     memset(&psMap, 0, sizeof(psMap));
376     
377     psMap.curNextInd = (data[0]>>7) & 0x1;
378     psMap.version = data[0] & 0x1f;
379     
380     data += 2;
381     
382     psMap.psInfoLen = (data[0] << 8) | data[1];
383     
384     data += psMap.psInfoLen;
385     
386     psMap.esStreamMapLen = (data[0] << 8) | data[1];
387     
388     psMap.esMapNum = psMap.esStreamMapLen / 4;
389     
390     for (i=0; i<psMap.esMapNum; i++)
391     {
392         if (i == MAX_ES_NUMS)
393         {
394             printf("now just save %d es info!\n", MAX_ES_NUMS);
395             
396             break;
397         }
398         
399         psMap.esMaps[i].streamType = data[0];
400         psMap.esMaps[i].esId = data[1];
401         psMap.esMaps[i].esInfoLen = (data[2] << 8) | data[3];
402         
403         data += (4+psMap.esMaps[i].esInfoLen);
404     }
405     
406 #ifdef PRINTF_DEBUG
407     int mNUm = 0;
408     
409     if (psMap.esMapNum > MAX_ES_NUMS)
410     {
411         mNUm = MAX_ES_NUMS;
412     }
413     
414     for (i=0; i<mNUm; i++)
415     {
416         printf("%s%sstreamNum: %d, streamType: %d, esId: %d\n",  TAB44, TAB44, i, psMap.esMaps[i].streamType, psMap.esMaps[i].esId);
417     }
418 #endif
419 }
420 
421 static void getPdts(unsigned char *pdtsData, long long *pdts, unsigned char *pdtsString)
422 {
423     int hour = 0;
424     int minute = 0;
425     int second = 0;
426     int msecond = 0;
427     
428     long long pts = 0;
429     long long pts2Ms = 0;
430 
431     unsigned char ptsStr[MAX_PDTS_STRING_LEN+1] = {0};
432     
433     /* 5個位元組轉33位的值 */
434     pts = (((pdtsData[0]>>1) & 0x7) << 30) | (pdtsData[1] << 22) | (((pdtsData[2]>>1) & 0x7f) << 15) | (pdtsData[3] << 7) | (pdtsData[4]>>1 & 0x7f);
435     
436     /* 90KHz, 1000ms/90 */
437     pts2Ms = pts/90;
438     
439     hour = pts2Ms/(60*60*1000);
440     minute = (pts2Ms - hour * (60*60*1000)) / (60*1000);
441     second = (pts2Ms - hour * (60*60*1000) - minute * (60*1000)) / 1000;
442     msecond = pts2Ms - hour * (60*60*1000) - minute * (60*1000) - second * 1000;
443     
444     sprintf(ptsStr, "%02d:%02d:%02d:%03d", hour, minute, second, msecond);
445     
446     ptsStr[MAX_PDTS_STRING_LEN] = '\0';
447     
448     memcpy(pdtsString, ptsStr, MAX_PDTS_STRING_LEN);
449     
450     *pdts = pts;
451 }
452 
453 /*********************************************************************************
454     startcode(24) + streamid(8) + pes_len(16) + {header: flag1(8) + flag2(8, pts標識在這兒) + header_len(8)} + {header_data(header_len, 若前面的flag有數據, 數據就在這兒)} + pes_data(pes_len-3-header_len)
455 **********************************************************************************/
456 static void parsePes(const unsigned char streamId, unsigned char* const pesData, const unsigned short pesLen)
457 {
458     unsigned char pts_dts_flag;
459     
460     static int audioNum = 0;
461     static int videoNum = 0;
462     static int privateNum = 0;
463     static int paddingNum = 0;
464     
465     unsigned char *data = NULL;
466     
467     unsigned char pts[MAX_PDTS_LEN+1] = {0};
468     unsigned char dts[MAX_PDTS_LEN+1] = {0};
469 
470     T_PS_PES psPes = {0};
471     
472     data = pesData;
473     
474     memset(&psPes, 0x0, sizeof(psPes));
475     
476     psPes.streamId = streamId;
477     
478     if (((streamId>=0xC0) && (streamId<=0xDF)) || ((streamId>=0xE0) && (streamId<=0xEF)))
479     {
480         pts_dts_flag = data[1]>>6 & 0x3;
481 
482         psPes.pesHeaderLen = data[2];
483         
484         data += 3;
485         
486         switch (pts_dts_flag)
487         {
488             case 0: /* 00, no pts, dts */
489                 break;
490             
491             case 2: /* 10, only pts*/
492                 memset(pts, 0x0, sizeof(pts));
493 
494                 memcpy(pts, data, MAX_PDTS_LEN);
495                 
496                 getPdts(pts, &psPes.pts, psPes.ptsStr);
497                 
498                 break;
499                 
500             case 3: /* 11 pts & dts*/
501                 memset(pts, 0x0, 
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 3D建築,bim技術,3d庫房,3d檔案室,3d密集架,webGL,threejs,3d機房 ...
  • 直接進入正題,滑鼠跟隨,顧名思義,就是元素會跟隨著滑鼠的移動而作出相應的運動。大概類似於這樣: 通常而言,CSS 負責表現,JavaScript 負責行為。而滑鼠跟隨這種效果屬於行為,要實現通常都需要藉助 JS。 當然,本文的重點,就是介紹如何在不藉助 JS 的情況下使用 CSS 來模擬實現一些滑鼠 ...
  • Web前端工程師是當前各大企業都比較稀缺的人才,薪資待遇和就業前景都很不錯。不論是專業還是非專業,有基礎亦或是無基礎,都想通過學習Web前端實現高薪就業。 ...
  • 一、新的變數聲明方式 let/cons 與var不同,新的變數聲明方式帶來了一些不一樣的特性,其中最重要的兩個特性就是提供了塊級作用域與不再具備變數提升。 若是對變數提升不怎麼瞭解的話可以去參考我的其他文章 javascript預編譯的過程 。 什麼是塊級作用域膩? 寫在 “{}” 內的內容 都是塊 ...
  • 前言 這一章主要講2個模式,一個是,適配器模式(負責將一個類的介面適配成用戶所期待的),另外一個是外觀模式(為子系統提供一個共同的對外介面),看完的第一反應是,為什麼要把它們兩放在同一章,難道它們有什麼不可告人的秘密? 難道是因為他們倆都很簡單嗎?不會不會,畢竟是大名鼎鼎的headfirst,怎麼可 ...
  • 官網 http://www.fhadmin.org/D 集成安全許可權框架shiro Shiro 是一個用 Java 語言實現的框架,通過一個簡單易用的 API 提供身份驗證和授權,更安全,更可靠E 集成ehcache分散式緩存 是一個純Java的進程內緩存框架,具有快速、精幹等特點,廣泛使用的開源J ...
  • 俗話說磨刀不誤砍柴工,確實,一早上花一個小時去磨刀一天下來肯定能多砍很多柴。我們做軟體開發也是同樣的道理,有套好開發框架在手裡,開發也是事半功倍。 那麼一套MVC快速開發框架至少得具有哪些功能才能幫我們做到高效率、高品質的開發呢?下麵我以力軟後臺管理系統開發框架為例談一談快速開發框架的幾個主要功能。 ...
  • Adapter(適配器模式) 加個“適配器”以便於復用 將一個類的介面轉換成客戶希望的另一個介面。Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。 應用場景 如果我們的代碼依賴一些外部的API,或者依賴一些可能會經常更改的類,那麼應該考慮用適配器模式。 你想使用一個已經存 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...