在很久之前曾分享过一个自动获取假日表的小工具,这个小工具是通过爬取国务院的节假日安排通知并清洗整理后得到的假日表,但因为国务院网站结构发生变化,这个小工具已经失效了。
由于假日表是PowerBI中很常用到的一种表,因此寻找到了另一个数据源进行爬取,本篇文章就来再次分享一下具体的做法与工具。
首先,新找到的节假日数据源如下图所示:
链接:https://tool.lu/index.php/holiday/index.html
因此通过爬取每年的放假安排时间表,就可以获得各节日的放假时间与调休日期,然后再加上排除了节假日与调休日期后剩下的所有周末日期即可得到完整的假日表,只要不在假日表中的日期就是工作日期。
基于此思路,可以使用PowerQuery进行爬取与处理,具体步骤或代码如下:
1、新建两个参数,StartYear
与 EndYear
,用来控制获取的假日表的年份范围。
2、创建一个函数用来获取法定节假日,代码如下:
GetHolidayOfYear = (x)=>
let
Url = "https://tool.lu/index.php/holiday/index.html?y="&Text.From(x),
Header = [#"user-agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0"],
Web = Web.Page(Web.Contents(Url,[Headers=Header])){[Caption=Text.From(x)&"年放假安排时间表"]}[Data]
in
try
List.Combine(
Table.TransformRows(
Web,(y)=>
List.Transform(
List.Transform(
Expression.Evaluate("{"&
Text.Combine(
List.Transform(
Text.SplitAny(y[放假时间],"-~—"),
each if Text.StartsWith(_,"12") then
Text.From(Number.From(Date.From(Text.Format("#{0}年",{x-1})&_)))
else
Text.From(Number.From(Date.From(Text.Format("#{0}年",{x})&_)))
),
".."
)&"}"
),
Date.From
),
each {_,y[节日],"法定节假日"}
)
)
)
otherwise {}
3、创建一个函数用来获取调休日期,代码如下:
GetWorkDayOfYear = (x)=>
let
Url = "https://tool.lu/index.php/holiday/index.html?y="&Text.From(x),
Header = [#"user-agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0"],
Web = Web.Page(Web.Contents(Url,[Headers=Header])){[Caption=Text.From(x)&"年放假安排时间表"]}[Data]
in
try
List.Combine(
List.Transform(
List.Select(Web[调休日期],each _<>"无调休"),each
List.Transform(
Text.SplitAny(_,"、,,;;"),
each if Text.StartsWith(_,"12") then
Date.From(Text.Format("#{0}年",{x-1})&Text.Trim(Text.BeforeDelimiter(_,"(")))
else
Date.From(Text.Format("#{0}年",{x})&Text.Trim(Text.BeforeDelimiter(_,"(")))
)
)
)
otherwise {}
4、创建一个查询,获取所有周末日期,并排除节假日与调休日期,代码如下:
Result - 假日表 =
let
HolidayDateList = List.Buffer(List.Combine(List.Transform({StartYear..EndYear},GetHolidayOfYear))),
WorkDateList = List.Buffer(List.Combine(List.Transform({StartYear..EndYear},GetWorkDayOfYear))),
TotalDayOfPeriod = List.Transform({Number.From(#date(StartYear,1,1))..Number.From(#date(EndYear,12,31))},each Date.From(_)),
TotalWeekDayOfPeriod = List.Select(TotalDayOfPeriod,each List.Contains({6,7},Date.DayOfWeek(_,Day.Monday)+1)),
AvailableWeekDayOfPeriod = List.RemoveItems(TotalWeekDayOfPeriod,WorkDateList & List.Transform(HolidayDateList,each _{0})),
TotalHoliday = HolidayDateList & List.Transform(AvailableWeekDayOfPeriod,each {_,"周末","公休日"})
in
Table.Sort(Table.FromRows(TotalHoliday,type table [日期=date,假日名称=text,假日类型=text]),"日期")
将上面给出的代码粘贴到Excel或PowerBI的PowerQuery查询中,即可得到指定年份范围的假日表。
为方便使用,下面使用PowerBI模板文件简单制作了一个小工具,只需要打开文件然后填入年份范围参数,即可自动获取假日表。如下图所示:
获取方式如下:
最后,由于是从其他网站中爬取的数据,因此不保证代码或工具的有效期。另外,如果获取的年份范围过大,可能会触发网站的反爬措施,当加载不出来时,可以尝试缩小年份范围。