Pandas學習筆記

来源:https://www.cnblogs.com/NSGUF/archive/2017/12/27/8127673.html
-Advertisement-
Play Games

Pandas基礎篇 Pandas基於Numpy開發,提供了很多高級的數據處理功能。 1、Pandas中的數據對象 Series和DataFrame是Pandas中最常用的兩個對象。 1.1 Series對象 是Pandas中最基本的對象,可用Numpy的數組處理函數直接對Series對象進行處理。支 ...


Pandas基礎篇

Pandas基於Numpy開發,提供了很多高級的數據處理功能。

1、Pandas中的數據對象

Series和DataFrame是Pandas中最常用的兩個對象。

1.1 Series對象

是Pandas中最基本的對象,可用Numpy的數組處理函數直接對Series對象進行處理。支持使用位置、索引標簽作為下標存取元素,與字典類似;每一個Series對象實際上由兩個數組組成。

print(pd.__version__)
s=pd.Series([1,3,2,4,5],index=['b','a','c','d','e'])#若index不指定,將自動創建位置下標的索引
print('索引:',s.index)
print('數組值:',s.values)
print('位置下標:',s[2])
print('標簽下標:',s['a'])
print('位置切片:',s[1:3])
print('標簽切片:',s['a':'c'])
print('位置列表存取元素:',s[[1,2,3]])#按照標簽的位置
print('標簽數組存取元素:',s[['b','c','d']])
print('字典功能:',list(s.iteritems()))
s2=pd.Series([20,30,40,50,60],index=['b','c','d','e','f'])
print(s+s2)#兩邊index都有則相加即可,若有一方沒有,則用NaN填充
print(s.value_counts())#元素中每個值得個數
str=pd.Series(['A','b','C','是','Baca',np.nan,'VASD','dafd'])
print(str.str.lower())# 對英文字母小寫

1.2 DataFrame 對象

DataFrame對象(數據表)是Pandas中最常用的數據對象。Pandas提供了很多數據結構轉換成DataFrame對象的方法,還提供很多輸入輸出函數來將各種文件格式轉換成DataFrame對象。

dates = pd.date_range('20130101', periods=6)#periods為個數
調用read_csv讀取數據,通過index_col指定第0,1列為索引,用parse_dates參數指定進行日期轉換列.在指定列時可以使用列的序號或列明。
df_soil=pd.read_csv('Soils-simple.csv',index_col=[0,1],parse_dates=['Date'])
df_soil=pd.read_csv('Soils-simple.csv',index_col=[0,1],parse_dates=['Date'])
df_soil.columns.name='Measures'

DataFrame對象是一個二維表格,其中每列中的元素必須一致,而不同列則可不同。object可保存任何python對象
print(df_soil.dtypes)#dtypes屬性獲得表示各個列類型的Series對象。
print(df_soil.shape)#行數和列數
print(df_soil)

print(df_soil.head(1))#查看頂部幾條數據
print(df_soil.tail(1))#查看底部幾條數據
print(df_soil.index)#查看行索引
print(df_soil.columns)#查看列索引
print(df_soil.values)#查看底層numpy的數據
print(df_soil.describe())#快速統計數據
print(df_soil.T)#行列互換
print(df_soil.sort_index(axis=0,ascending=False))#根據軸排序,axis為1表橫軸,反之縱軸,ascending為True表正序,反之 反序
print(df_soil.sort_values(by='pH'))#按照值排序,指定某縱軸對應的值,列排序


#DataFrame對象用油行索引和列索引,並可通過索引標簽對數據進行存取。
print('columns:',df_soil.columns)# 列索引
print('index:',df_soil.index)# 行索引
print('columnsname:',df_soil.columns.name)
print('indexname:',df_soil.index.name)
#運算符可通過列索引標簽獲取指定列,當下標是單個便簽時,所得到的是Series對象,當下標是列表時,則是新的DataFrame對象。
print('pH:',df_soil['pH'])
print('Dens,Ca:',df_soil[['Dens','Ca']])
#通過行索引獲取指定的行
print('df.loc:',df_soil.loc['0-10','Top'])
print('df.loc:',df_soil.loc[['10-30']])
print(df_soil.values.dtype)
print('===============將記憶體中的數據轉換成DataFrame對象===================')
import numpy as np

# 將形狀為4,2的二維數組轉換成DataFrame對象,通過index和columns參數指定行和列的索引
df1 = pd.DataFrame(np.random.randint(0, 10, (4, 2)), index=['A', 'B', 'C', 'D'], columns=['a', 'b'])
# 將字典轉換成DataFrame,列索引有字典的鍵決定,行索引有index參數指定
df2 = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [5, 6, 7, 8]}, index=['A', 'B', 'C', 'D'])
# 將結構數組轉行成DataFrame對象,列索引由結構數組的欄位名決定,行索引預設從0開始的整數序列。
df3 = pd.DataFrame(
    np.array([('item1', 1), ('item2', 2), ('item3', 3), ('item4', 4)], dtype=[('name', '10S'), ('count', 'int')]))

print(df1)
print(df2)
print(df3)

dict1 = {'a': [1, 2, 3], 'b': [4, 5, 6]}
dict2 = {'a': {'A': 1, 'B': 2}, 'b': {'A': 3, 'C': 4}}

# orient參數指定字典鍵對應的方向,預設columns,表示把字典的鍵轉換成為列索引
df1 = pd.DataFrame.from_dict(dict1, orient='index')
df2 = pd.DataFrame.from_dict(dict1, orient='columns')
df3 = pd.DataFrame.from_dict(dict2, orient='index')
df4 = pd.DataFrame.from_dict(dict2, orient='columns')

print(df1)
print(df2)
print(df3)
print(df4)

df1 = pd.DataFrame.from_items(dict1.items(), orient='index', columns=['A', 'B', 'C'])
df2 = pd.DataFrame.from_items(dict1.items(), orient='columns')

print(df1)
print(df2)

print("======將DataFrame對象轉換成其他格式的數據======")
print(df2.to_dict(orient='records'))#字典列表
print(df2.to_dict(orient='list'))#列表列表
print(df2.to_dict(orient='dict'))#嵌套字典
print(df2.to_records(index=False).dtype)#轉換成結構數組,index表示返回是否行索引數據
print(df2.to_records(index=True).dtype)#轉換成結構數組,index表示返回是否行索引數據

np.random.seed(42)
dates =pd.Index(['r1','r2','r3','r4','r5'],name='level')
df=pd.DataFrame(np.random.randint(0,10,(5,3)),index=dates,columns=['c1','c2','c3'])
print(df)
pieces=[df[:2],df[2:4],df[4:]]
print(pd.concat(pieces))#連接

left=pd.DataFrame({'key':['foo','foo'],'lval':[1,2]})
right=pd.DataFrame({'key':['foo','foo'],'rval':[4,5]})
print(pd.merge(left,right,on='key'))# 將一樣key的值對應鏈接
left=pd.DataFrame({'key':['foo','bar'],'lval':[1,2]})
right=pd.DataFrame({'key':['foo','bar1'],'rval':[4,5]})
print(pd.merge(left,right,on='key'))# 將一樣key的值對應鏈接

print(df.append(df.iloc[3],ignore_index=False))# 添加第4行,ignore_index表示忽略給的行號 自動標從0開始。

print(df[['c1']])
print(df[['c1','c2']])
print(df[2:4])#表示第2行到第4-1行
print(df['r2':'r4'])#表示第2行到第4-1行
print(df[df.c1>4])#c1列大於4的行
print(df[df>2])#對象中大於2的顯示,否則用NaN填充

df2=df.copy()
df2['c4']=[1,2,3,4,5]
print(df2)
print(df2['c4'].isin([1,2,3]))#篩選c4列中值為1,2,3的為True

df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])#放大或縮小原df
# df1.loc[dates[0]:dates[1],'E'] = 1
print(df1)

print(df1.dropna(how='any'))#刪除所有有NaN的行
print(df1.fillna(value=5))#將所有NaN的值轉換成5

print(df1.isnull())#將每個位置的值判斷是否nan
print(df)
print(df.mean())#每列的平均值
print(df.mean(1))#每行的平均值
s=pd.Series([1,3,5,np.nan,6],index=dates)
print(s)
print(s.shift(1))#在最前面放1個nan,然後再加入s,長度為原來的長度
print(df.sub(s,axis='index'))#對應s的行減去s的位置的值。減nan,則成nan
print(df.apply(np.cumsum))#累積求和,從列的上到下
print(df.apply(lambda x:x.max()-x.min()))#一列中的最大減去最小
dfgroup = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
                   'B' : ['one', 'one', 'two', 'three','two', 'two', 'one', 'three'],
                   'C' : np.random.randn(8),'D' : np.random.randn(8)})
print(dfgroup.groupby('A').sum())# 通過A列中的值,求出同樣值的和
print(dfgroup.groupby('A').size())# 通過A列中的值,求出同樣值的個數

print(dfgroup.groupby(['A','B']).sum())# 通過A、B列中的值,求出同樣值的和

tuples = list(zip(*[['bar', 'bar', 'baz', 'baz',
                    'foo', 'foo', 'qux', 'qux'],
                    ['one', 'two', 'one', 'two',
                    'one', 'two', 'one', 'two']]))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])
print(df[:4])
df2 = df[:4]
print(df2.stack())#將列對應加入行,變成原行*列的行數
print(df2.stack().unstack())#變回來
print(df2.stack().unstack(1))# 將多級索引中第2個變為列
print(df2.stack().unstack(0))# 將多級索引中第1個變為列

df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3,
                   'B' : ['A', 'B', 'C'] * 4,
                   'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
                   'D' : np.random.randn(12),
                   'E' : np.random.randn(12)})
print(pd.pivot_table(df, values='D', index=['A', 'B'], columns=['C']))# 將D列數據拿出來,行為A、B排列組合,列為C中的值
rng = pd.date_range('1/1/2012', periods=100, freq='S')# 時間排100s freq表示單位
# print(rng)

ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
print(ts.resample('5Min').sum())#列印5分鐘內的總數

1.3 Index對象

Index對象保存索引標簽數據,它可快速找到標簽對應的整數下標

index=df_soil.columns
print(index)
print(index.values)

# Index對象可當做一維數組,可通過NumPy數組相同的下標操作獲取新的Index對象,但是只可讀,不可改。
print(index[[1,3]])
print(index>'c')
print(index[index>'c'])
print(index[1::2])
# 獲取映射值
print(index.get_loc('Ca'))#獲取位置
print(index.get_indexer(['Dens','Conduc']))#以數組排序,若不存在 返回-1
# 可直接調用Index()創建Index對象,再傳遞給DataFrame的index或columns,又由於Index不可變,則多個數據可共用一個Index對象
index=pd.Index(['A','B','C'],name='level')
s1=pd.Series([1,2,3],index=index)
df1=pd.DataFrame({'a':[1,2,3],'b':[4,5,6]},index=index)
print(s1.index,df1.index)

1.4 MultiIndex對象

MultiIndex對象表示多級索引,繼承Index,其中的多級標簽採用元組對象表示

mindex=df_soil.index
print(mindex[1])
print(mindex.get_loc(('0-10','Slope')))
print(mindex.get_indexer([('10-30','Top')]))
# 內部並不直接保存元組對象,而是使用多個Index對象保存索引中每級的標簽
print(mindex.levels[0])
print(mindex.levels[1])

#使用多個整數數組保存標簽下標
print(mindex.labels[0])
print(mindex.labels[1])
# 獲得所有元組列表

level0,level1=mindex.levels
label0,label1=mindex.labels

print(list(zip(level0[label0],level1[label1])))

# 將一個元組列表傳遞給Index()時,將自動創建MultiIndex對象
print(pd.Index([('A','x'),('A','y'),('B','x'),('B','y')],name=['class1','class2'],tupleize_cols=True))#tupleize_cols參數表示是否為MultiIndex對象
print(pd.MultiIndex.from_arrays([['A','A','B','B'],['x','y','x','y']],names=['class1','class2']))#多個數組創建MultiIndex對象
midx=pd.MultiIndex.from_product([['A','B','C'],['X','Y']],names=['class1','class2'])#使用笛卡爾積創建MultiIndex對象
print(midx)
print(pd.DataFrame(np.random.randint(0,10,(6,6)),columns=midx,index=midx))

1.5 常用的函數參數

參數 常用值 說明
axis 0、1 運算對應的軸
level 整數或索引的級別名 指定運算對應的級別
fill_value 數值 指定運算中出現的NaN的代替填充值
skipna 布爾值 運算是否跳過NaN
index 序列 指定行索引
columns 序列 指定列索引
numeric_only 布爾值 是否只針對數值進行運算
func 可調用函數 指定回調函數
inplace 布爾值 是否原地更新,若為否,則返回新對象
encoding utf8 指定文本編碼
dropna 布爾值 是否刪除包好NaN的行

2、下標存取

2.1 []操作符

通過[]操作符對DataFrame對象進行存取時,支持以下5中下標對象:

import numpy as np
np.random.seed(42)
df=pd.DataFrame(np.random.randint(0,10,(5,3)),index=['r1','r2','r3','r4','r5'],columns=['c1','c2','c3'])
print(df)
  • 單個索引標簽:獲取標簽對應的列,返回一個Series對象。

    print(df[['c1']])
  • 多個索引標簽:獲取以列表、數組(註意不能是元組)表示多個標簽對應的列,返回一個DataFrame對象

    print(df[['c1','c2']])
  • 整數切片:以整數下標獲取切片對應的行。

    print(df[2:4])#表示第2行到第4-1行
  • 標簽切片:當使用標簽作為切片時包含終值。

    print(df['r2':'r4'])#表示第2行到第4-1行
  • 布爾數組:獲取數組中True對應的行。

    print(df[df.c1>4])#c1列大於4的行
  • 布爾DataFrame:將DataFrame對象中False對應的元素設置為NaN。

    print(df[df>2])#對象中大於2的顯示,否則用NaN填充

2.2 .loc[]和.iloc[]存取器

print(df.loc['r2'])#r2行
print(df.loc['r2','c2'])#第r2行的第c2列
print(df.loc[['r2','r3']])#r2,與r3行
print(df.loc[['r2','r3'],['c2','c3']])#r2和r3所對應的c2於c3列
print(df.loc['r2':'r4',['c2','c3']])#r2到r4所對應的c2,c3列
print(df.loc[df.c1>2,['c1','c2']])#c1列大於2的c1與c2列

.iloc與.ioc類似,不過它是使用整數下標。

print(df.iloc[1])#r2行
print(df.iloc[[1,2]])#r2,與r3行
print(df.iloc[[1,2],[1,2]])#r2和r3所對應的c2於c3列
print(df.iloc[1:3,[1,2]])#r2到r4所對應的c2,c3列
print(df.iloc[df.c1.values>2,[0,1]])#c1列大於2的c1與c2列

.ix[]存取器,混用標簽和位置下標。

print(df.ix[2:4,['c1','c2']])
print(df.ix['r1':'r3',[0,1]])

獲取單個值

print(df.at['r2','c2'])
print(df.iat[1,1])
print(df.get_value('r2','c2'))#比.at速度要快
print(df.lookup(['r2','r4','r3'],['c1','c2','c1']))#獲取指定元素數組

多級標簽的存取

print(df_soil.loc[np.s_[:'Top'],['pH','Ca']])#np.s_對象創建第0軸對應的下標。

query()方法

print(df.query('c1>3 and c2<4'))#條件查詢 可使用no、and、or等關鍵字,可使用全局變數
low=3
hi=4
print(df.query('c1>@low and c2<@hi'))

3、文件的輸入輸出

輸入輸出函數

函數名 說明
read_csv() 從CSV格式的文本文件讀取數據
read_excel() 從Excel文件讀入數據
HDFStore() 使用HDF5文件讀寫數據
read_sql() 從SQL資料庫的查詢結果載入數據
read_pickle() 讀入Pickle序列化之後的數據

3.1 CSV格式

df_list=[]
for df in pd.read_csv(
    '201406.csv',
    encoding='utf-8',#編碼
    chunksize=100,#一次讀入的行數
    usecols=['時間','監測點','AQI','PM2.5','PM10'],#只讀入這些列
    na_values=['-',''],#這些字元串表示缺失數據
    parse_dates=[0]#第一列為時間列
    ):
    df_list.append(df)

print(df_list[0].count())
print(df_list[0].dtypes)

df.to_csv('foo.csv')#寫入數據
df.to_excel('foo.xlsx', sheet_name='Sheet1')#寫入數據
pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA'])#讀取數據

3.2 HDF5文件

HDF5用於存儲科學計算數據,支持大於2G的文件。採用二進位格式保存數據,可以對數據進行壓縮存儲,比文本文件更節省空間,存取也更迅速。

df.to_hdf('foo.h5','df')#寫入數據
pd.read_hdf('foo.h5','df')#讀取數據

store=pd.HDFStore('a.hdf5',complib='blosc',complevel=9)#complib指定使用blosc壓縮數據,通過complevel指定壓縮級別
df1=pd.DataFrame(np.random.rand(100000,4),columns=list('ABCD'))
df2=pd.DataFrame(np.random.randint(0,1000,(10000,3)),columns=['one','two','three'])
s1=pd.Series(np.random.rand(1000))
store['dataframes/df1']=df1
store['dataframes/df2']=df2
store['dataframes/s1']=s1

print(store.keys())
print(df1.equals(store['dataframes/df1']))

root=store.get_node("//")#獲取根節點,
for node in root._f_walknodes():#調用_f_walknodes()遍歷其包含的所有節點。
    print(node)

#往已保存進HDFStore的DataFrame追加數據
store.append('dataframe/df_dynamic1',df1,append=False)#append為False表示是否覆蓋已存在的數據

df3=pd.DataFrame(np.random.rand(100,4),columns=list('ABCD'))
store.append('dataframe/df_dynamic1',df3)
print(store['dataframes/df_dynamic1'].shape)

#使用append()創建pytables中支持索引的表格(Table)節點,預設使用DataFrame的index作為索引。通過select可對其進行查詢 index表DataFrame的標簽數據
print(store.select('dataframe/df_dynamic1',where='index>97 & index<102'))#表示行在97-102所有的行,該方法減少記憶體使用量和磁碟讀取速度以及數據的訪問速度,在添加df3時是添加不是覆蓋,所以有兩個98,99

#若希望對DataFrame的指定列進行索引,可以在用append創建新的表格時,通過data_columns指定索引列
store.append('dataframes/df_dynamic1', df1, append=False, data_columns=['A', 'B'])
print(store.select('dataframes/df_dynamic1' , where='A > 0.99 & B <0.01'))

在將對個文本文件的數據逐次寫入HDF5文件時,需要註意以下幾點:
1.HDF5文件不支持Unicode字元串,因此需要對Unicode字元串進行編碼,轉換為位元組字元串。由於文件可能包含UTF-8的BOM,因此在讀取文件的頭三個位元組並與BOM比較。
2.需要使用dtype參數指定這些數值列的類型為浮點數。
3.需要為HDF5文件中的字元串列指定最大長度,否則該最大長度將由第一個被添加進HDF5文件的數據對象決定。

註意:由於所有從CSV文件讀入DataFrame對象的行索引都為預設值,因此HDF5文件中的數據的行索引並不是唯一的。

3.3 Pickle序列化

df = pd.DataFrame(np.random.randint(0, 10, (4, 2)), index=['A', 'B', 'C', 'D'], columns=['a', 'b'])
df.to_pickle('df.pickle')
df_aqi2=pd.read_pickle('df.pickle')
print(df.equals(df_aqi2))

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • GCC4和GCC5使用的C++標準庫下,string的名字不一樣,導致鏈接錯誤。 ...
  • 抽象類(abstract) 以下麵多態的示例來說明: 父類Animal中的sing()方法遲早要被子類Cat、Dog重寫,而且在多態實現下,Animal的sing()完全是多餘的。因此,可以將Animal的sing()方法的方法體刪掉。 更徹底一點,將sing()方法加上abstract關鍵字,這個 ...
  • 一. 問題: 在使用solr時, 分詞器解析中文的時候, 是一個一個字解析的. 這並不是我們想要的結果. 而在lucene中, 使用的中文分詞器是 IKAnalyzer. 那麼在solr裡面, 是不是任然可以用這個呢. 二. 整合 ik 1. 修改schema配置文件 打開如下路徑中的managed ...
  • #有‘*’為重點import timeprint(time.time())#以秒的形式返回******time.sleep(3) ******print(time.clock()) #cpu執行的時間print(time.gmtime()) # 結構化時間,本初子午線那裡的時間time.struct ...
  • 一 前段時間自學了一段時間的Python,想著濃一點項目來練練手。看著大佬們一說就是爬了100W+的數據就非常的羡慕,不過對於我這種初學者來說,也就爬一爬圖片。 我相信很多人的第一個爬蟲程式都是爬去貼吧的圖片,嗯,我平時不玩貼吧,加上我覺得豆瓣挺良心的,我就爬了豆瓣首頁上面的圖片。其實最剛開始是想爬 ...
  • 本文簡單的介紹了Servlet處理響應的基本流程以及Servlet的生命周期 ...
  • 一、wxPython介紹 1、wxPython是Python語言的一套優秀的GUI圖形庫。wxPython可以很方便的創建完整的、功能鍵全的GUI用戶界面。 wxPython是作為優秀的跨平臺GUI庫wxWidgets的Python封裝和Python模塊的方式提供給用戶的。 2、wxPython是跨 ...
  • 原題是這樣的: 給出一個字元串數組S,找到其中所有的亂序字元串(Anagram)。如果一個字元串是亂序字元串,那麼他存在一個字母集合相同,但順序不同的字元串也在S中。 樣例 對於字元串數組 ["lint","intl","inlt","code"] 返回 ["lint","inlt","intl"] ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...