Py之模塊

来源:https://www.cnblogs.com/zxfprogram/archive/2017/12/30/8150679.html
-Advertisement-
Play Games

模塊&包(* * * * *) 模塊(modue)的概念: 在電腦程式的開發過程中,隨著程式代碼越寫越多,在一個文件里代碼就會越來越長,越來越不容易維護。 為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件里,這樣,每個文件包含的代碼就相對較少,很多編程語言都採用這種組織代碼的方式。在P ...


模塊&包(* * * * *)

模塊(modue)的概念:

在電腦程式的開發過程中,隨著程式代碼越寫越多,在一個文件里代碼就會越來越長,越來越不容易維護。

為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件里,這樣,每個文件包含的代碼就相對較少,很多編程語言都採用這種組織代碼的方式。在Python中,一個.py文件就稱之為一個模塊(Module)。

使用模塊有什麼好處?

最大的好處是大大提高了代碼的可維護性。

其次,編寫代碼不必從零開始。當一個模塊編寫完畢,就可以被其他地方引用。我們在編寫程式的時候,也經常引用其他模塊,包括Python內置的模塊和來自第三方的模塊。

所以,模塊一共三種:

  • python標準庫
  • 第三方模塊
  • 應用程式自定義模塊

另外,使用模塊還可以避免函數名和變數名衝突。相同名字的函數和變數完全可以分別存在不同的模塊中,因此,我們自己在編寫模塊時,不必考慮名字會與其他模塊衝突。但是也要註意,儘量不要與內置函數名字衝突。

模塊導入方法

1 import 語句

1 import module1[, module2[,... moduleN]

當我們使用import語句的時候,Python解釋器是怎樣找到對應的文件的呢?答案就是解釋器有自己的搜索路徑,存在sys.path里。  

1 2 ['', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload''/usr/local/lib/python3.4/dist-packages''/usr/lib/python3/dist-packages']  

因此若像我一樣在當前目錄下存在與要引入模塊同名的文件,就會把要引入的模塊屏蔽掉。

2  from…import 語句

1 from modname import name1[, name2[, ... nameN]]

這個聲明不會把整個modulename模塊導入到當前的命名空間中,只會將它裡面的name1或name2單個引入到執行這個聲明的模塊的全局符號表。

3  From…import* 語句

1 from modname import *

這提供了一個簡單的方法來導入一個模塊中的所有項目。然而這種聲明不該被過多地使用。大多數情況, Python程式員不使用這種方法,因為引入的其它來源的命名,很可能覆蓋了已有的定義。

4 運行本質 

1 2 #1 import test #2 from test import add  

無論1還是2,首先通過sys.path找到test.py,然後執行test腳本(全部執行),區別是1會將test這個變數名載入到名字空間,而2只會將add這個變數名載入進來。  

包(package)

如果不同的人編寫的模塊名相同怎麼辦?為了避免模塊名衝突,Python又引入了按目錄來組織模塊的方法,稱為包(Package)。

舉個例子,一個abc.py的文件就是一個名字叫abc的模塊,一個xyz.py的文件就是一個名字叫xyz的模塊。

現在,假設我們的abcxyz這兩個模塊名字與其他模塊衝突了,於是我們可以通過包來組織模塊,避免衝突。方法是選擇一個頂層包名:

                                           

引入了包以後,只要頂層的包名不與別人衝突,那所有模塊都不會與別人衝突。現在,view.py模塊的名字就變成了hello_django.app01.views,類似的,manage.py的模塊名則是hello_django.manage。

請註意,每一個包目錄下麵都會有一個__init__.py的文件,這個文件是必須存在的,否則,Python就把這個目錄當成普通目錄(文件夾),而不是一個包。__init__.py可以是空文件,也可以有Python代碼,因為__init__.py本身就是一個模塊,而它的模塊名就是對應包的名字。

調用包就是執行包下的__init__.py文件

 註意點(important)

1--------------

在nod1里import  hello是找不到的,有同學說可以找到呀,那是因為你的pycharm為你把myapp這一層路徑加入到了sys.path裡面,所以可以找到,然而程式一旦在命令行運行,則報錯。有同學問那怎麼辦?簡單啊,自己把這個路徑加進去不就OK啦:

1 2 3 4 5 import sys,os BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) import hello hello.hello1()

2 --------------

1 2 if __name__=='__main__':     print('ok')

“Make a .py both importable and executable”

      如果我們是直接執行某個.py文件的時候,該文件中那麼”__name__ == '__main__'“是True,但是我們如果從另外一個.py文件通過import導入該文件的時候,這時__name__的值就是我們這個py文件的名字而不是__main__。

      這個功能還有一個用處:調試代碼的時候,在”if __name__ == '__main__'“中加入一些我們的調試代碼,我們可以讓外部模塊調用的時候不執行我們的調試代碼,但是如果我們想排查問題的時候,直接執行該模塊文件,調試代碼能夠正常運行!s

3   

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ##-------------cal.py def add(x,y):       return x+y ##-------------main.py import cal      #from module import cal   def main():       cal.add(1,2)       ##--------------bin.py from module import main   main.main()
# from module import cal 改成 from . import cal同樣可以,這是因為bin.py是我們的執行腳本,
# sys.path里有bin.py的當前環境。即/Users/yuanhao/Desktop/whaterver/project/web這層路徑,
# 無論import what ,  解釋器都會按這個路徑找。所以當執行到main.py時,import cal會找不到,因為
# sys.path里沒有/Users/yuanhao/Desktop/whaterver/project/web/module這個路徑,而
#  from  module/.  import cal 時,解釋器就可以找到了。

time模塊(* * * *)

三種時間表示

在Python中,通常有這幾種方式來表示時間:

  • 時間戳(timestamp) :         通常來說,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。我們運行“type(time.time())”,返回的是float類型。
  • 格式化的時間字元串
  • 元組(struct_time)   :         struct_time元組共有9個元素共九個元素:(年,月,日,時,分,秒,一年中第幾周,一年中第幾天,夏令時)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 import time   # 1 time() :返回當前時間的時間戳 time.time()  #1473525444.037215   #----------------------------------------------------------   # 2 localtime([secs]) # 將一個時間戳轉換為當前時區的struct_time。secs參數未提供,則以當前時間為準。 time.localtime() #time.struct_time(tm_year=2016, tm_mon=9, tm_mday=11, tm_hour=0, # tm_min=38, tm_sec=39, tm_wday=6, tm_yday=255, tm_isdst=0) time.localtime(1473525444.037215)   #----------------------------------------------------------   # 3 gmtime([secs]) 和localtime()方法類似,gmtime()方法是將一個時間戳轉換為UTC時區(0時區)的struct_time。   #----------------------------------------------------------   # 4 mktime(t) : 將一個struct_time轉化為時間戳。 print(time.mktime(time.localtime()))#1473525749.0   #----------------------------------------------------------   # 5 asctime([t]) : 把一個表示時間的元組或者struct_time表示為這種形式:'Sun Jun 20 23:21:05 1993'。 # 如果沒有參數,將會將time.localtime()作為參數傳入。 print(time.asctime())#Sun Sep 11 00:43:43 2016   #----------------------------------------------------------   # 6 ctime([secs]) : 把一個時間戳(按秒計算的浮點數)轉化為time.asctime()的形式。如果參數未給或者為 # None的時候,將會預設time.time()為參數。它的作用相當於time.asctime(time.localtime(secs))。 print(time.ctime())  # Sun Sep 11 00:46:38 2016   print(time.ctime(time.time()))  # Sun Sep 11 00:46:38 2016   # 7 strftime(format[, t]) : 把一個代表時間的元組或者struct_time(如由time.localtime()和 # time.gmtime()返回)轉化為格式化的時間字元串。如果t未指定,將傳入time.localtime()。如果元組中任何一個 # 元素越界,ValueError的錯誤將會被拋出。 print(time.strftime("%Y-%m-%d %X", time.localtime()))#2016-09-11 00:49:56   # 8 time.strptime(string[, format]) # 把一個格式化時間字元串轉化為struct_time。實際上它和strftime()是逆操作。 print(time.strptime('2011-05-05 16:37:06''%Y-%m-%d %X'))   #time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6, #  tm_wday=3, tm_yday=125, tm_isdst=-1)   #在這個函數中,format預設為:"%a %b %d %H:%M:%S %Y"。     # 9 sleep(secs) # 線程推遲指定的時間運行,單位為秒。   # 10 clock() # 這個需要註意,在不同的系統上含義不同。在UNIX系統上,它返回的是“進程時間”,它是用秒錶示的浮點數(時間戳)。 # 而在WINDOWS中,第一次調用,返回的是進程運行的實際時間。而第二次之後的調用是自第一次調用以後到現在的運行 # 時間,即兩次時間差。

              

1 2 help(time) help(time.asctime)

random模塊(* *)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import random   print(random.random())#(0,1)----float   print(random.randint(1,3))  #[1,3]   print(random.randrange(1,3)) #[1,3)   print(random.choice([1,'23',[4,5]]))#23   print(random.sample([1,'23',[4,5]],2))#[[4, 5], '23']   print(random.uniform(1,3))#1.927109612082716     item=[1,3,5,7,9] random.shuffle(item) print(item)
複製代碼
import random

def v_code():

    code = ''
    for i in range(5):

        num=random.randint(0,9)
        alf=chr(random.randint(65,90))
        add=random.choice([num,alf])
        code += str(add)
    return code

print(v_code())
複製代碼

 os模塊(* * * *)

os模塊是與操作系統交互的一個介面

複製代碼
os.getcwd() 獲取當前工作目錄,即當前python腳本工作的目錄路徑
os.chdir("dirname")  改變當前腳本工作目錄;相當於shell下cd
os.curdir  返回當前目錄: ('.')
os.pardir  獲取當前目錄的父目錄字元串名:('..')
os.makedirs('dirname1/dirname2')    可生成多層遞歸目錄
os.removedirs('dirname1')    若目錄為空,則刪除,並遞歸到上一級目錄,如若也為空,則刪除,依此類推
os.mkdir('dirname')    生成單級目錄;相當於shell中mkdir dirname
os.rmdir('dirname')    刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir dirname
os.listdir('dirname')    列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式列印
os.remove()  刪除一個文件
os.rename("oldname","newname")  重命名文件/目錄
os.stat('path/filename')  獲取文件/目錄信息
os.sep    輸出操作系統特定的路徑分隔符,win下為"\\",Linux下為"/"
os.linesep    輸出當前平臺使用的行終止符,win下為"\t\n",Linux下為"\n"
os.pathsep    輸出用於分割文件路徑的字元串 win下為;,Linux下為:
os.name    輸出字元串指示當前使用平臺。win->'nt'; Linux->'posix'
os.system("bash command")  運行shell命令,直接顯示
os.environ  獲取系統環境變數
os.path.abspath(path)  返回path規範化的絕對路徑
os.path.split(path)  將path分割成目錄和文件名二元組返回
os.path.dirname(path)  返回path的目錄。其實就是os.path.split(path)的第一個元素
os.path.basename(path)  返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是絕對路徑,返回True
os.path.isfile(path)  如果path是一個存在的文件,返回True。否則返回False
os.path.isdir(path)  如果path是一個存在的目錄,則返回True。否則返回False
os.path.join(path1[, path2[, ...]])  將多個路徑組合後返回,第一個絕對路徑之前的參數將被忽略
os.path.getatime(path)  返回path所指向的文件或者目錄的最後存取時間
os.path.getmtime(path)  返回path所指向的文件或者目錄的最後修改時間
複製代碼

sys模塊(* * *)

1 2 3 4 5 6 sys.argv           命令行參數List,第一個元素是程式本身路徑 sys.exit(n)        退出程式,正常退出時exit(0) sys.version        獲取Python解釋程式的版本信息 sys.maxint         最大的Int sys.path           返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變數的值 sys.platform       返回操作系統平臺名稱

進度條:

import sys,time
for i in range(10):
    sys.stdout.write('#')
    time.sleep(1)
    sys.stdout.flush()

json & pickle(* * * *)

之前我們學習過用eval內置方法可以將一個字元串轉成python對象,不過,eval方法是有局限性的,對於普通的數據類型,json.loads和eval都能用,但遇到特殊類型的時候,eval就不管用了,所以eval的重點還是通常用來執行一個字元串表達式,並返回表達式的值。

1 2 3 4 import json x="[null,true,false,1]" print(eval(x)) print(json.loads(x))

什麼是序列化?

我們把對象(變數)從記憶體中變成可存儲或傳輸的過程稱之為序列化,在Python中叫pickling,在其他語言中也被稱之為serialization,marshalling,flattening等等,都是一個意思。

序列化之後,就可以把序列化後的內容寫入磁碟,或者通過網路傳輸到別的機器上。

反過來,把變數內容從序列化的對象重新讀到記憶體里稱之為反序列化,即unpickling。

json

如果我們要在不同的編程語言之間傳遞對象,就必須把對象序列化為標準格式,比如XML,但更好的方法是序列化為JSON,因為JSON表示出來就是一個字元串,可以被所有語言讀取,也可以方便地存儲到磁碟或者通過網路傳輸。JSON不僅是標準格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。

JSON表示的對象就是標準的JavaScript語言的對象,JSON和Python內置的數據類型對應如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #----------------------------序列化 import json   dic={'name':'alvin','age':23,'sex':'male'} print(type(dic))#<class 'dict'>   j=json.dumps(dic) print(type(j))#<class 'str'>     f=open('序列化對象','w') f.write(j)  #-------------------等價於json.dump(dic,f) f.close() #-----------------------------反序列化<br> import json f=open('序列化對象') data=json.loads(f.read())#  等價於data=json.load(f)
複製代碼
import json
#dct="{'1':111}"#json 不認單引號
#dct=str({"1":111})#報錯,因為生成的數據還是單引號:{'one': 1}

dct='{"1":"111"}'
print(json.loads(dct))

#conclusion:
#        無論數據是怎樣創建的,只要滿足json格式,就可以json.loads出來,不一定非要dumps的數據才能loads
複製代碼

pickle 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ##----------------------------序列化 import pickle   dic={'name':'alvin','age':23,'sex':'male'}   print(type(dic))#<class 'dict'>   j=pickle.dumps(dic) print(type(j))#<class 'bytes'>     f=open('序列化對象_pickle','wb')#註意是w是寫入str,wb是寫入bytes,j是'bytes' f.write(j)  #-------------------等價於pickle.dump(dic,f)   f.close() #-------------------------反序列化 import pickle f=open('序列化對象_pickle','rb')   data=pickle.loads(f.read())#  等價於data=pickle.load(f)     print(data['age'])    

      Pickle的問題和所有其他編程語言特有的序列化問題一樣,就是它只能用於Python,並且可能不同版本的Python彼此都不相容,因此,只能用Pickle保存那些不重要的數據,不能成功地反序列化也沒關係。

shelve模塊(* * *)

 shelve模塊比pickle模塊簡單,只有一個open函數,返回類似字典的對象,可讀可寫;key必須為字元串,而值可以是python所支持的數據類型

1 2 3 4 5 6 7 8 9 10 11 12 import shelve   = shelve.open(r'shelve.txt')   # f['stu1_info']={'name':'alex','age':'18'} # f['stu2_info']={'name':'alvin','age':'20'} # f['school_info']={'website':'oldboyedu.com','city':'beijing'} # # # f.close()   print(f.get('stu_info')['age'])

xml模塊(* *)

xml是實現不同語言或程式之間進行數據交換的協議,跟json差不多,但json使用起來更簡單,不過,古時候,在json還沒誕生的黑暗年代,大家只能選擇用xml呀,至今很多傳統公司如金融行業的很多系統的介面還主要是xml。

xml的格式如下,就是通過<>節點來區別數據結構的:

複製代碼
<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>
複製代碼

xml協議在各個語言里的都 是支持的,在python中可以用以下模塊操作xml:

複製代碼
import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
 
#遍歷xml文檔
for child in root:
    print(child.tag, child.attrib)
    for i in child:
        print(i.tag,i.text)
 
#只遍歷year 節點
for node in root.iter('year'):
    print(node.tag,node.text)
#---------------------------------------

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
 
#修改
for node in root.iter('year'):
    new_year = int(node.text) + 1
    node.text = str(new_year)
    node.set("updated","yes")
 
tree.write("xmltest.xml")
 
 
#刪除node
for country in root.findall('country'):
   rank = int(country.find('rank').text)
   if rank > 50:
     root.remove(country)
 
tree.write('output.xml')
複製代碼

自己創建xml文檔:

複製代碼
import xml.etree.ElementTree as ET
 
 
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
 
et = ET.ElementTree(new_xml) #生成文檔對象
et.write("test.xml", encoding="utf-8",xml_declaration=True)
 
ET.dump(new_xml) #列印生成的格式
複製代碼

configparser模塊(* *)

來看一個好多軟體的常見文檔格式如下:

1 2 3 4 5 6 7 8 9 10 11 12 [DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes    [bitbucket.org] User = hg    [topsecret.server.com] Port = 50022 ForwardX11 = no

如果想用python生成一個這樣的文檔怎麼做呢?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import configparser    config = configparser.ConfigParser() config["DEFAULT"= {'ServerAliveInterval''45',                       'Compression''yes',                      'CompressionLevel''9'}    config['bit
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildPr ...
  • 1 class Person(): 2 def __init__(self, name): 3 self.name = name 4 5 6 def print_name(self): 7 print(self.name) 8 9 p = Person('Li') 10 import types 1... ...
  • 非原創,系轉載。 ...
  • 1.JDK API 中關於Serializable的描述 類通過實現 java.io.Serializable 介面以啟用其序列化功能。未實現此介面的類將無法使其任何狀態序列化或反序列化。可序列化類的所有子類型本身都是可序列化的。序列化介面沒有方法或欄位,僅用於標識可序列化的語義。 序列化運行時使用 ...
  • 何為Miller Rabin演算法 首先看一下度娘的解釋(如果你懶得讀直接跳過就可以反正也沒啥亂用:joy:) Miller-Rabin演算法是目前主流的基於概率的素數測試演算法,在構建密碼安全體系中占有重要的地位。通過比較各種素數測試演算法和對Miller-Rabin演算法進行的仔細研究,證明在電腦中構建 ...
  • Description Input 第一行:CAS,代表數據組數(不大於350),以下CAS行,每行一個數字,保證在64位長整形範圍內,並且沒有負數。你需要對於每個數字:第一,檢驗是否是質數,是質數就輸出Prime 第二,如果不是質數,輸出它最大的質因數是哪個。 第一行:CAS,代表數據組數(不大於 ...
  • 使用python的requests開發爬蟲類程式時,經常需要將之前請求返回的set-cookie值,作為下一個請求的cookie發送。比如模擬登錄之後的返回的sessionId,就需要作為後續請求的cookie參數。 網上找了一圈,發現很多說需要手動添加或設置cookie的值。殊不知cookie是與 ...
  • 數據類型 電腦顧名思義就是可以做數學計算的機器,因此,電腦程式理所當然地可以處理各種數值。但是,電腦能處理的遠不止數值,還可以處理文本、圖形、音頻、視頻、網頁等各種各樣的數據,不同的數據,需要定義不同的數據類型。在Python中,能夠直接處理的數據類型有以下幾種 一 Number(數字) 1. ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...