生活随笔
收集整理的這篇文章主要介紹了
python学习之钉钉打卡
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
python學習之釘釘打卡
背景
曾經寫過幾個python小工具,刷快手、自動答題、刷火車票、爬電影天堂電影…,最近因為釘釘成了我們公司官方軟件,所以,你懂得啦,呵呵。剛好手頭有個退休的小米4安卓機,讓python來釘釘打卡,這需要借助adb,因為只有adb才能讓我們的電腦跟安卓手機交互。該文章內容僅僅只是為了學習,最好不要用于實際打卡(要打我也攔不住)。
原理
python命令行庫顯示調用adb,利用adb命令做點擊、截屏、滑動操作。adb獲取當前屏幕布局xml,解析xml,找到需要點擊或者滑動的元素,實現安卓手機的控制。adb打卡操作成功后,做一個python郵件或者短信通知提醒打卡結果。
實現
一、準備
首先要下載一個adb工具,這里我直接下載好了一個工具。VSCode最新版、python3.7
二、代碼
python需要調用adb工具,首先寫一個通用的cmd命令行工具類。
import shlex
import datetime
import subprocess
import time
def executeCommand(cmd
,cwd
=None,timeout
=None,shell
=False):if shell
:cmdStringList
= cmd
else:cmdStringList
= shlex
.split
(cmd
)if timeout
:endTime
= datetime
.datetime
.now
() + datetime
.timedelta
(seconds
=timeout
)sub
= subprocess
.Popen
(cmdStringList
,cwd
=cwd
,stdin
=subprocess
.PIPE
,stdout
=subprocess
.PIPE
,shell
=shell
,bufsize
=4096)while sub
.poll
() is None:time
.sleep
(0.1)if timeout
:if endTime
<= datetime
.datetime
.now
():raise Exception
('Timeout: {}'.format(cmd
))return sub
.stdout
.read
()if __name__
== "__main__":print(executeCommand
("ls"))
獲取安卓設備編號
currentPath
= os
.getcwd
()
print('當前路徑:{}'.format(currentPath
))
print('start------預殺死存在的adb.exe------start')
cuscmd
.executeCommand
('taskkill /im adb.exe /f',currentPath
)
print('end------預殺死存在的adb.exe------end')
out
=cuscmd
.executeCommand
('adb/adb devices',currentPath
)
deviceListStr
=out
.decode
(encoding
="utf-8")
print('設備編號:{}'.format(deviceListStr
))
執行點擊
deviceListStr
= deviceListStr
.split
('\r\n',3)[3]
deviceList
=re
.findall
(r
'[A-Za-z0-9/.:]+',deviceListStr
)
total
= len(deviceList
)
if len(deviceList
) > 1:dtotal
= Decimal
(total
)deviceNum
= (Decimal
(dtotal
))/Decimal
(2)print('發現'+str(deviceNum
)+'臺手機設備')deviceId
= []for i
in range(0,int(deviceNum
)):deviceId
.append
(deviceList
[2*i
])print(deviceId
)for id in deviceId
:cmdStr
= 'adb/adb -s '+id+' shell dumpsys window policy|grep "mScreenOnEarly"'out
=cuscmd
.executeCommand
(cmdStr
,currentPath
)returnStr
=out
.decode
(encoding
="utf-8").strip
()print('獲取屏幕信息:{}'.format(returnStr
))if 'mScreenOnEarly=false' in returnStr
:print('當前設備屏幕熄滅,點亮屏幕')cuscmd
.executeCommand
('adb/adb -s '+id+' shell input keyevent 26',currentPath
)out
=cuscmd
.executeCommand
('adb/adb -s '+id+' shell am force-stop com.alibaba.android.rimet',currentPath
)stopStr
=out
.decode
(encoding
="utf-8").strip
()print('關閉信息:{}'.format(stopStr
))out
=cuscmd
.executeCommand
('adb/adb -s '+id+' shell am start -n com.alibaba.android.rimet/com.alibaba.android.rimet.biz.LaunchHomeActivity',currentPath
)startStr
=out
.decode
(encoding
="utf-8").strip
()print('啟動信息:{}'.format(startStr
))time
.sleep
(15)listdir
=os
.listdir
(currentPath
)tempPath
= os
.path
.join
(currentPath
,'temp')if 'temp' not in listdir
:print('文件夾temp不存在,創建temp')os
.mkdir
(tempPath
)tempPath
= tempPath
.replace
('\\','/')out
=cuscmd
.executeCommand
('adb/adb -s '+id+' shell getprop ro.product.model',currentPath
)modelStr
=out
.decode
(encoding
="utf-8").strip
().replace
(r
' ','_')print('獲取設備名稱:{}'.format(modelStr
))out
=cuscmd
.executeCommand
('adb/adb -s '+id+' shell pm dump com.alibaba.android.rimet | grep "versionName"',currentPath
)returnStr
=out
.decode
(encoding
="utf-8").strip
()ddVersion
= re
.findall
(r
'[0-9/.:]+',returnStr
)[0]print('獲取釘釘版本號:{}'.format(ddVersion
))listdir
=os
.listdir
(tempPath
)DDClick
(id,modelStr
,ddVersion
,currentPath
,tempPath
,listdir
).clickWork
().clickKQDK
().clickSXBDK
().showResult
()out
=cuscmd
.executeCommand
('adb/adb -s '+id+' shell am force-stop com.alibaba.android.rimet',currentPath
)stopStr
=out
.decode
(encoding
="utf-8").strip
()print('關閉信息:{}'.format(stopStr
))
else :print('未發現任何手機設備')
print('結束')
具體點擊操作的類 ddclick
import cuscmd
from decimal
import Decimal
import time
import re
import os
import utils
import json
import datetime
import qqemail
class DDClick:def __init__(self
,id,modelStr
,ddVersion
,currentPath
,tempPath
,listdir
):self
.mainXMLName
= modelStr
+'_'+ddVersion
+'_mainui.xml'self
.workXMLName
= modelStr
+'_'+ddVersion
+'_workui.xml'self
.sxbdkXMLName
= modelStr
+'_'+ddVersion
+'_sxbdkui.xml'self
.listdir
= listdirself
.tempPath
= tempPathself
.currentPath
= currentPathself
.id = iddef showResult(self
):xmlName
= self
.sxbdkXMLNametempPath
= self
.tempPathcurrentPath
= self
.currentPath
id = self
.idself
.__createXML
(id,xmlName
,self
.listdir
,currentPath
,tempPath
,force
=True)with open(os
.path
.join
(tempPath
,xmlName
), 'r',encoding
='utf-8') as f
:xmlContentStr
= json
.dumps
(utils
.xmlToJsonDict
(f
.read
())).encode
('utf-8').decode
('unicode_escape')f
.close
()index
= 0index
= xmlContentStr
.find
("打卡時間")totalIndex
= len(xmlContentStr
)-1self
.__screencapDK
(id,currentPath
,tempPath
)base64Str
= utils
.imgToBase64
(os
.path
.join
(tempPath
,'dkscreen.png'))emailtemplate
= ''with open('emailtemplate.txt', 'r',encoding
='utf-8') as hf
:emailtemplate
= hf
.read
()hf
.close
()while index
> -1:sIndex
= xmlContentStr
.rfind
('@content-desc',0,index
-17)eIndex
= xmlContentStr
.find
('@content-desc',index
,totalIndex
)printValue
= '打卡時間'printValue1
= '打開地址'if sIndex
>-1 and eIndex
>-1:sbTimeStr
= xmlContentStr
[sIndex
+17:sIndex
+26]dkTimeStr
= xmlContentStr
[eIndex
+17:eIndex
+22]sNodeIndex
= xmlContentStr
.find
('node"',eIndex
,totalIndex
)dkAddressStr
= ''sDKAddressIndex
= 0searchIndex
= sNodeIndex
+6while len(dkAddressStr
) == 0 and sDKAddressIndex
>= 0:sDKAddressIndex
= xmlContentStr
.find
('@content-desc',searchIndex
,totalIndex
)eDKAddressIndex
= xmlContentStr
.find
('",',sDKAddressIndex
+13,totalIndex
)dkAddressStr
= xmlContentStr
[sDKAddressIndex
+17:eDKAddressIndex
]searchIndex
= eDKAddressIndex
+6printValue
=sbTimeStr
+' '+printValue
+''+dkTimeStrprintValue1
= printValue1
+' '+dkAddressStrprintStr
= '''-------------------------打卡結果-------------------------{}{}---------------------------------------------------------'''.format(printValue
,printValue1
)print(printStr
)emailStr
= emailtemplate
.format(sbTimeStr
,dkTimeStr
,dkAddressStr
,base64Str
)qqemail
.sendhtml
(emailStr
)index
= xmlContentStr
.find
("打卡時間",index
+4)def clickSXBDK(self
):currentDateTime
= datetime
.datetime
.now
()print('>>>當前系統時間:{}'.format(datetime
.datetime
.strftime
(currentDateTime
, "%Y-%m-%d %H:%M")))currentDateStr
= datetime
.datetime
.strftime
(currentDateTime
,'%Y-%m-%d')xmlName
= self
.sxbdkXMLNametempPath
= self
.tempPathcurrentPath
= self
.currentPath
id = self
.idself
.__createXML
(id,xmlName
,self
.listdir
,currentPath
,tempPath
,force
=True)try:sbTimeStr
= currentDateStr
+' '+self
.__getSXBTime
(xmlName
,'上班時間')print('>>>今天上班時間:{}<<<'.format(sbTimeStr
))xbTimeStr
= currentDateStr
+' '+self
.__getSXBTime
(xmlName
,'下班時間')print('>>>今天下班時間:{}<<<'.format(xbTimeStr
))sbTime
= datetime
.datetime
.strptime
(sbTimeStr
, "%Y-%m-%d %H:%M")xbTime
= datetime
.datetime
.strptime
(xbTimeStr
, "%Y-%m-%d %H:%M")if currentDateTime
< sbTime
:print('>>>上班打卡<<<')self
.__click
(xmlName
,0,0,'上班打卡',self
.__clickByPoint
)if currentDateTime
> xbTime
:print('>>>下班打卡<<<')self
.__click
(xmlName
,0,0,'下班打卡',self
.__clickByPoint
)else:print('>>>不在打卡范圍,正確范圍是:{}前,或{}后<<<'.format(sbTimeStr
,xbTimeStr
))except Exception
as e
:print(e
)self
.clickSXBDK
()return self
def clickKQDK(self
):workXMLName
= self
.workXMLNametempPath
= self
.tempPathcurrentPath
= self
.currentPath
id = self
.idself
.__createXML
(id,workXMLName
,self
.listdir
,currentPath
,tempPath
)self
.__click
(workXMLName
,0,-22,'考勤打卡',self
.__clickByPoint
)return self
def clickWork(self
):mainXMLName
= self
.mainXMLNametempPath
= self
.tempPathcurrentPath
= self
.currentPath
id = self
.idself
.__createXML
(id,mainXMLName
,self
.listdir
,currentPath
,tempPath
)with open(os
.path
.join
(tempPath
,mainXMLName
), 'r',encoding
='utf-8') as f
:mainuiDict
=utils
.xmlToJsonDict
(f
.read
())nodes
= mainuiDict
['hierarchy']['node']['node']['node']['node']['node']['node']['node']for node
in nodes
:if node
['@resource-id'] == 'com.alibaba.android.rimet:id/bottom_tab':nodeItems
= node
['node']for nodeItem
in nodeItems
:if 'node' in nodeItem
:nodeChildren
= nodeItem
['node']for nodeChild
in nodeChildren
:if nodeChild
['@resource-id'] == 'com.alibaba.android.rimet:id/home_bottom_tab_button_work':zbStr
= nodeChild
['@bounds']self
.__clickByPoint
(zbStr
)return self
def __createXML(self
,id,xmlName
,listdir
,currentPath
,tempPath
,force
= False):cmd
= 'adb/adb -s '+id+' shell "dumpsys window | grep mCurrentFocus"'out
=cuscmd
.executeCommand
(cmd
,currentPath
)returnStr
=out
.decode
(encoding
="utf-8").strip
()print('獲取頁面所在activity信息:{}'.format(returnStr
))if 'com.alibaba.android.rimet' not in returnStr
:cuscmd
.executeCommand
('adb/adb -s '+id+' shell input keyevent 26',currentPath
)cmd
= 'adb/adb -s '+id+' shell dumpsys window policy|grep "mScreenOnEarly"'out
=cuscmd
.executeCommand
(cmd
,currentPath
)returnStr
=out
.decode
(encoding
="utf-8").strip
()print('獲取屏幕信息:{}'.format(returnStr
))if 'mScreenOnEarly=false' in returnStr
:print('當前設備屏幕熄滅,點亮屏幕')cuscmd
.executeCommand
('adb/adb -s '+id+' shell input keyevent 26',currentPath
)if xmlName
not in listdir
or force
is True:print(xmlName
+'不存在或強制更新'+xmlName
+',創建新的'+xmlName
)cmd
= 'adb/adb -s '+id+' shell uiautomator dump /data/local/tmp/'+xmlNameout
=cuscmd
.executeCommand
(cmd
,currentPath
)returnStr
=out
.decode
(encoding
="utf-8").strip
()print('獲取頁面UIXML信息:{}'.format(returnStr
))cmd
= 'adb/adb -s '+id+' pull /data/local/tmp/'+xmlName
+' '+tempPathout
=cuscmd
.executeCommand
(cmd
,currentPath
)returnStr
=out
.decode
(encoding
="utf-8").strip
()print('保存頁面UIXML信息:{}'.format(returnStr
))def __screencapDK(self
,id,currentPath
,tempPath
,imgName
='dkscreen.png'):cmd
= 'adb/adb -s '+id+' shell screencap -p /data/local/tmp/'+imgNameout
=cuscmd
.executeCommand
(cmd
,currentPath
)returnStr
=out
.decode
(encoding
="utf-8").strip
()print('獲取釘釘打卡截屏:{}'.format(returnStr
))cmd
= 'adb/adb -s '+id+' pull /data/local/tmp/'+imgName
+' '+tempPathout
=cuscmd
.executeCommand
(cmd
,currentPath
)returnStr
=out
.decode
(encoding
="utf-8").strip
()print('保存釘釘打卡截屏:{}'.format(returnStr
))def __clickByPoint(self
,zbStr
,xoffset
=0,yoffset
=0):print('當前點擊坐標范圍為:{}'.format(zbStr
))zbList
= re
.findall
(r
'[0-9]+',zbStr
)lx
= Decimal
(zbList
[0])ly
= Decimal
(zbList
[1])rx
= Decimal
(zbList
[2])ry
= Decimal
(zbList
[3])mx
= lx
+(rx
-lx
)/2+xoffsetmy
= ly
+(ry
-ly
)/2+yoffset
print('當前點擊坐標為:{}'.format('['+str(round(mx
,0))+','+str(round(my
,0))+']'))mPointStr
= str(round(mx
,0))+' '+str(round(my
,0))out
=cuscmd
.executeCommand
('adb/adb -s '+self
.id+' shell input tap '+mPointStr
,self
.currentPath
)clickStr
=out
.decode
(encoding
="utf-8").strip
()print('點擊信息:{}'.format(clickStr
))time
.sleep
(6)def __click(self
,xmlName
,xoffset
=0,yoffset
=0,keywords
='',callback
=None):tempPath
= self
.tempPath
with open(os
.path
.join
(tempPath
,xmlName
), 'r',encoding
='utf-8') as f
:workuiStr
= json
.dumps
(utils
.xmlToJsonDict
(f
.read
())).encode
('utf-8').decode
('unicode_escape')index
= workuiStr
.find
(keywords
)if index
> -1:sIndex
= workuiStr
.rfind
('{',0,index
)eIndex
= workuiStr
.find
('}',index
,len(workuiStr
)-1)if sIndex
>-1 and eIndex
>-1:kqdkStr
= workuiStr
[sIndex
:eIndex
+1]kqdkDict
= json
.loads
(kqdkStr
)zbStr
= kqdkDict
['@bounds']if callback
!= None:callback
(zbStr
,xoffset
,yoffset
)def __getSXBTime(self
,xmlName
,keyWords
):tempPath
= self
.tempPathtimeStr
= Nonewith open(os
.path
.join
(tempPath
,xmlName
), 'r',encoding
='utf-8') as f
:xmlContentStr
= f
.read
()index
= xmlContentStr
.find
(keyWords
)if index
> -1:timeStr
= xmlContentStr
[index
+4:index
+9]print('得到的時間為:{}'.format(timeStr
))return timeStr
郵件通知
import smtplib
from email
.mime
.text
import MIMEText
from email
.header
import Header
host
='smtp.qq.com'
user
='xxxxx@qq.com'
pwd
=''
receive
=['xxxxx@qq.com']def send(msg
):try:smtp
= smtplib
.SMTP
()smtp
.connect
(host
, 25)smtp
.login
(user
, pwd
)smtp
.sendmail
(user
, receive
, msg
.as_string
())smtp
.quit
()print(">>>郵件發送成功!<<<")except smtplib
.SMTPException
as e
:print(">>>郵件發送失敗<<<", e
)def sendhtml(content
):msg
= MIMEText
(content
, 'html', 'utf-8')msg
['From'] = Header
("釘釘自動打卡助手", 'utf-8')msg
['To'] = Header
('釘釘用戶', 'utf-8')subject
= '釘釘自動打卡郵件通知'msg
['subject'] = Header
(subject
, 'utf-8')send
(msg
)
email模板
<meta charset
="utf-8"><div
class="content-wrap" style
="margin: 0px auto; overflow: hidden; padding: 0px; border: 0px solid rgb(238, 238, 238); width: 600px;"><!----><div
class="full" tindex
="1" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 600px;"><tbody
><tr
><td style
="direction: ltr; width: 600px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="left" style
="font-size: 0px; padding: 20px;"><div
class="text" style
="font-family: "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: center; line-height: 24px; color: rgb(250, 137, 123); font-size: 24px;"><div
><p style
="text-size-adjust: none; word-break: break-word; line-height: 24px; font-size: 24px; margin: 0px;"><strong
>打卡時間
</strong
></p
></div
></div
></td
></tr
></table
></td
></tr
></tbody
></table
></div
><div tindex
="2" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" style
="background-color: rgb(134, 227, 206); background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 1% 50%;"><tbody
><tr
><td style
="direction: ltr; font-size: 0px; text-align: center; vertical-align: top; width: 600px;"><table width
="100%" border
="0" cellpadding
="0" cellspacing
="0" style
="vertical-align: top;"><tbody
><tr
><td style
="width: 33.3333%; max-width: 33.3333%; min-height: 1px; font-size: 13px; text-align: left; direction: ltr; vertical-align: top; padding: 0px;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 200px;"><tbody
><tr
><td style
="direction: ltr; font-size: 0px; padding-top: 0px; text-align: center; vertical-align: top;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="center" vertical
-align
="middle" style
="padding-top: 40px; width: 200px; background-image: url(""); background-size: 100px; background-position: 10% 50%; background-repeat: no-repeat;"></td
></tr
></table
></td
></tr
></tbody
></table
></div
></td
><td style
="width: 33.3333%; max-width: 33.3333%; min-height: 1px; font-size: 13px; text-align: left; direction: ltr; vertical-align: top; padding: 0px;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 200px;"><tbody
><tr
><td style
="direction: ltr; width: 200px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="left" style
="font-size: 0px; padding: 26px 20px;"><div
class="text" style
="font-family: "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: center; line-height: 12px; color: rgb(32, 32, 32); font-size: 16px;"><div
><p style
="text-size-adjust: none; word-break: break-word; line-height: 12px; font-size: 16px; margin: 0px;"><strong
>{0}
</strong
></p
></div
></div
></td
></tr
></table
></td
></tr
></tbody
></table
></div
></td
><td style
="width: 33.3333%; max-width: 33.3333%; min-height: 1px; font-size: 13px; text-align: left; direction: ltr; vertical-align: top; padding: 0px;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 200px;"><tbody
><tr
><td style
="direction: ltr; font-size: 0px; padding-top: 0px; text-align: center; vertical-align: top;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="center" vertical
-align
="middle" style
="padding-top: 40px; width: 200px; background-image: url(""); background-size: 100px; background-position: 10% 50%; background-repeat: no-repeat;"></td
></tr
></table
></td
></tr
></tbody
></table
></div
></td
></tr
></tbody
></table
></td
></tr
></tbody
></table
></div
><div tindex
="3" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" style
="background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 1% 50%;"><tbody
><tr
><td style
="direction: ltr; font-size: 0px; text-align: center; vertical-align: top; width: 600px;"><table width
="100%" border
="0" cellpadding
="0" cellspacing
="0" style
="vertical-align: top;"><tbody
><tr
><td style
="width: 25%; max-width: 25%; min-height: 1px; font-size: 13px; text-align: left; direction: ltr; vertical-align: top; padding: 0px;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 150px;"><tbody
><tr
><td style
="direction: ltr; font-size: 0px; padding-top: 0px; text-align: center; vertical-align: top;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="center" vertical
-align
="middle" style
="padding-top: 120px; background-color: rgb(255, 221, 148); width: 150px; background-image: url(""); background-size: 100px; background-position: 10% 50%; background-repeat: no-repeat;"></td
></tr
></table
></td
></tr
></tbody
></table
></div
></td
><td style
="width: 25%; max-width: 25%; min-height: 1px; font-size: 13px; text-align: left; direction: ltr; vertical-align: top; padding: 0px;"><div columnnumber
="3"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" style
="width: 100%;"><tbody
><tr
><td style
="direction: ltr; font-size: 0px; text-align: center; vertical-align: top; border: 0px;"><a target
="_blank" href
="javascript:;" style
="cursor: default;"><div
class="mj-column-per-50" style
="width: 100%; max-width: 100%; font-size: 13px; text-align: left; direction: ltr; display: inline-block; vertical-align: top;"><table border
="0" cellpadding
="0" cellspacing
="0" width
="100%" style
="border-collapse: collapse; border-spacing: 0px; width: 100%; vertical-align: top;"><tr
><td align
="center" border
="0" style
="font-size: 0px; word-break: break-word;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 150px;"><tbody
><tr
><td style
="direction: ltr; width: 150px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-color: rgb(221, 230, 165); background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="left" style
="font-size: 0px; padding: 20px;"><div
class="text" style
="font-family: "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: right; line-height: 20px; color: rgb(32, 32, 32); font-size: 16px;"><div
><p style
="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 16px; margin: 0px;"><strong
>打卡時間
</strong
></p
></div
></div
></td
></tr
></table
></td
></tr
></tbody
></table
></div
></td
></tr
></table
></div
><div
class="mj-column-per-50" style
="width: 100%; max-width: 100%; font-size: 13px; text-align: left; direction: ltr; display: inline-block; vertical-align: top;"><table border
="0" cellpadding
="0" cellspacing
="0" width
="100%" style
="border-collapse: collapse; border-spacing: 0px; width: 100%; vertical-align: top;"><tr
><td align
="center" border
="0" style
="font-size: 0px; word-break: break-word;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 150px;"><tbody
><tr
><td style
="direction: ltr; width: 150px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-color: rgb(221, 230, 165); background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="left" style
="font-size: 0px; padding: 20px;"><div
class="text" style
="font-family: "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: right; line-height: 20px; color: rgb(32, 32, 32); font-size: 16px;"><div
><p style
="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 16px; margin: 0px;"><strong
>打卡地址
</strong
></p
></div
></div
></td
></tr
></table
></td
></tr
></tbody
></table
></div
></td
></tr
></table
></div
></a
></td
></tr
></tbody
></table
></div
></td
><td style
="width: 50%; max-width: 50%; min-height: 1px; font-size: 13px; text-align: left; direction: ltr; vertical-align: top; padding: 0px;"><div columnnumber
="3"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" style
="width: 100%;"><tbody
><tr
><td style
="direction: ltr; font-size: 0px; text-align: center; vertical-align: top; border: 0px;"><a target
="_blank" href
="javascript:;" style
="cursor: default;"><div
class="mj-column-per-50" style
="width: 100%; max-width: 100%; font-size: 13px; text-align: left; direction: ltr; display: inline-block; vertical-align: top;"><table border
="0" cellpadding
="0" cellspacing
="0" width
="100%" style
="border-collapse: collapse; border-spacing: 0px; width: 100%; vertical-align: top;"><tr
><td align
="center" border
="0" style
="font-size: 0px; word-break: break-word;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 300px;"><tbody
><tr
><td style
="direction: ltr; width: 300px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-color: rgb(255, 221, 148); background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="left" style
="font-size: 0px; padding: 20px;"><div
class="text" style
="font-family: "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: left; line-height: 20px; color: rgb(32, 32, 32); font-size: 16px;"><div
><p style
="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 16px; margin: 0px;"><strong
>{1}</strong
></p
></div
></div
></td
></tr
></table
></td
></tr
></tbody
></table
></div
></td
></tr
></table
></div
><div
class="mj-column-per-50" style
="width: 100%; max-width: 100%; font-size: 13px; text-align: left; direction: ltr; display: inline-block; vertical-align: top;"><table border
="0" cellpadding
="0" cellspacing
="0" width
="100%" style
="border-collapse: collapse; border-spacing: 0px; width: 100%; vertical-align: top;"><tr
><td align
="center" border
="0" style
="font-size: 0px; word-break: break-word;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 300px;"><tbody
><tr
><td style
="direction: ltr; width: 300px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top; background-color: rgb(255, 221, 148); background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 10% 50%;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td align
="left" style
="font-size: 0px; padding: 20px;"><div
class="text" style
="font-family: "Microsoft YaHei"; overflow-wrap: break-word; margin: 0px; text-align: left; line-height: 20px; color: rgb(32, 32, 32); font-size: 16px;"><div
><p style
="text-size-adjust: none; word-break: break-word; line-height: 20px; font-size: 16px; margin: 0px;"><strong
>{2}</strong
></p
></div
></div
></td
></tr
></table
></td
></tr
></tbody
></table
></div
></td
></tr
></table
></div
></a
></td
></tr
></tbody
></table
></div
></td
></tr
></tbody
></table
></td
></tr
></tbody
></table
></div
><div tindex
="4" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" style
="background-color: rgb(255, 255, 255); background-image: url(""); background-repeat: no-repeat; background-size: 100px; background-position: 1% 50%;"><tbody
><tr
><td style
="direction: ltr; font-size: 0px; text-align: center; vertical-align: top; width: 600px;"><table width
="100%" border
="0" cellpadding
="0" cellspacing
="0" style
="vertical-align: top;"><tbody
><tr
><td style
="width: 100%; max-width: 100%; min-height: 1px; font-size: 13px; text-align: left; direction: ltr; vertical-align: top; padding: 0px;"><div
class="full" style
="margin: 0px auto; max-width: 600px;"><table align
="center" border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" style
="width: 600px;"><tbody
><tr
><td style
="direction: ltr; width: 600px; font-size: 0px; padding-bottom: 0px; text-align: center; vertical-align: top;"><div style
="display: inline-block; vertical-align: top; width: 100%;"><table border
="0" cellpadding
="0" cellspacing
="0" role
="presentation" width
="100%" style
="vertical-align: top;"><tr
><td style
="font-size: 0px; word-break: break-word; background-color: rgb(204, 171, 216); width: 580px; text-align: center; padding: 10px;"><div
><img height
="auto" alt
="釘釘打卡圖片" width
="580" src
="{3}" style
="box-sizing: border-box; border: 0px; display: inline-block; outline: none; text-decoration: none; height: auto; max-width: 100%; padding: 0px;"></div
></td
></tr
></table
></div
></td
></tr
></tbody
></table
></div
></td
></tr
></tbody
></table
></td
></tr
></tbody
></table
></div
></div
>
釘釘打卡成功后通知截圖
8. 完整代碼請訪問我的碼云鏈接。
總結
以上是生活随笔為你收集整理的python学习之钉钉打卡的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。