鱼C论坛

 找回密码
 立即注册
查看: 1884|回复: 4

[技术交流] Python:每日一题 144

[复制链接]
发表于 2018-1-19 08:39:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 jerryxjr1220 于 2018-1-20 13:14 编辑

我们的玩法做了一下改变:

1. 楼主不再提供答案。
2. 请大家先独立思考”,再参考其他鱼油的解答,这样才有助于自己编程水平的提高。
3. 鼓励大家积极答题,奖励的期限为出题后24小时内。
4. 根据答案的质量给予1~3鱼币的奖励。

题目:
今年是2018年啦,那么请统计一下,今年一共有多少假期,可以休息多少天?(双休日不计)
不限制用什么方法,库,爬虫都可以。大家尽管发挥!

例如:
日期                节假日        放假天数
2018-01-01        元旦                1天


提供一个API接口做参考:
http://www.easybots.cn/holiday_api.net

2018年公共假日:
https://publicholidays.cn/zh/2018-dates/

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-1-19 19:48:44 | 显示全部楼层
  1. import re
  2. import datetime as dt
  3. import requests as req


  4. def get(url):
  5.     return req.get(url).text

  6. def parse(html):
  7.     res = []
  8.     # 获取第一个tbody
  9.     tbody = re.findall(r'<tbody>(.*?)</tbody>', html)[0]
  10.     # 获取tbody中的所有tr
  11.     trs = re.findall('<tr.*?>(.*?)</tr>', tbody)
  12.     for tr in trs:
  13.         # 从tr中获取开始时间和结束时间的时间节点
  14.         ds = re.findall('datetime="\D*(\d*)-(\d*)-(\d*)\D*"',tr)
  15.         ds = [[int(y) for y in x] for x in ds]
  16.         # 计算放假天数
  17.         if len(ds) == 1:
  18.             days = 1
  19.         elif len(ds) == 2:
  20.             start = dt.date(ds[0][0],ds[0][1],ds[0][2])
  21.             end = dt.date(ds[1][0],ds[1][1],ds[1][2])
  22.             days = (end-start).days + 1
  23.         else:
  24.             raise ValueError("some thing wrong!!!")
  25.         # 获取节日名称
  26.         name = re.findall('class="summary.*?>(.*?)<',tr)[0]
  27.         res.append([ds[0],name,days])
  28.     return res
  29.         
  30.         
  31. def fun( url ):
  32.     html = get(url)
  33.     res = parse(html)
  34.     print('日期\t\t\t节假日\t\t放假天数')
  35.     for x in res:
  36.         print('%d-%02d-%02d\t\t%s\t\t%d' %(x[0][0],x[0][1],x[0][2],x[1],x[2]))
  37.     s = sum( x[2] for x in res)
  38.     print('总天数为:',s)

  39. def main():
  40.     url = 'https://publicholidays.cn/zh/2018-dates/'
  41.     fun(url)

  42. if __name__ == "__main__":
  43.     main()
复制代码

结果:
  1. 日期                        节假日                放假天数
  2. 2018-01-01                元旦                1
  3. 2018-02-15                春节                7
  4. 2018-04-05                清明节                3
  5. 2018-04-29                劳动节                3
  6. 2018-06-16                端午节                3
  7. 2018-09-22                中秋节                3
  8. 2018-10-01                国庆日                7
  9. 总天数为: 27
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 贡献 +3 收起 理由
jerryxjr1220 + 3 + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-1-20 19:10:28 | 显示全部楼层
爬虫方面很渣啊,希望楼主给个答案瞅瞅

这个接口网站说要授权码啊,否则返回垃圾数据,
结果试了一下,果然同一个日期返回的结果会不一样
  1. from urllib import request
  2. from collections import Counter

  3. def fun(year=2018):
  4.     date = ",".join(str(year*100 + i) for i in range(1, 13))
  5.     url = "http://www.easybots.cn/api/holiday.php?m=" + date # 网站有说明用法
  6.     response = request.urlopen(url)
  7.     html = response.read()

  8.     result = Counter(j for i in eval(html).values() for j in i.values())
  9.     return result['2'] # 据网站说明'2'为节假日
复制代码

第二个直接给出日期的网站,感觉要获取信息很麻烦啊
连儿童节、青年节、妇女节和建军节都加上去了,结果是31天
  1. from urllib import request
  2. import bs4
  3. import chardet
  4. import datetime

  5. def fun2(year=2018):
  6.     result = 0
  7.     url = "https://publicholidays.cn/zh/{}-dates/".format(year)

  8.     head = {}
  9.     head['User-Agent'] =  'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19'

  10.     req = request.Request(url, headers=head)
  11.     response = request.urlopen(req).read()
  12.     detect_result = chardet.detect(response)
  13.     html = response.decode(detect_result['encoding'])

  14.     # 这段都是审查元素后出来的,日期都放在名为time的tag里,按照"假期开始日~结束日"样式放的
  15.     aim_tag = bs4.SoupStrainer('time')
  16.     soup = bs4.BeautifulSoup(html, 'lxml', parse_only=aim_tag)
  17.     for i in soup('time'):
  18.         if 'dtstart' in i['class']:
  19.             result += 1
  20.             temp_start = datetime.datetime.strptime(i['datetime'], "%Y-%m-%d")
  21.         elif 'dtend' in i['class']:
  22.             temp_end = datetime.datetime.strptime(i['datetime'], "%Y-%m-%d")
  23.             result += (temp_end - temp_start).days
  24.     return result
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2018-1-20 22:32:42 From FishC Mobile | 显示全部楼层
solomonxian 发表于 2018-1-20 19:10
爬虫方面很渣啊,希望楼主给个答案瞅瞅

这个接口网站说要授权码啊,否则返回垃圾数据,

是的,第一个接口要注册一下才能用。
第二个是直接返回了连续假期,扣除双休日后应该就是正确答案。
支持中国假期的库是比较少的,支持西方假期的库就有很多,比如pandas等
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-2-13 12:31:11 | 显示全部楼层
用xpath写了一个

  1. import requests as req
  2. from lxml import etree
  3. from datetime import datetime
  4. from datetime import timedelta

  5. url = "https://publicholidays.cn/zh/2018-dates/"
  6. text = req.get(url).text
  7. selector = etree.HTML(text)
  8. total_days = 0
  9. print("日期\t\t\t\t节假日\t\t放假天数")
  10. for i in range(1,8):
  11.    
  12.     date = selector.xpath("//*[@id='row-inner-travel']/article/div[1]/table[1]/tbody/tr[%d]/td[1]/time/text()"%i)
  13.     name = selector.xpath("//*[@id='row-inner-travel']/article/div[1]/table[1]/tbody/tr[%d]/td[3]/span/text()"%i)
  14.     if not len(name):
  15.         name = selector.xpath("//*[@id='row-inner-travel']/article/div[1]/table[1]/tbody/tr[%d]/td[3]/a/text()"%i)

  16.     last = (datetime.strptime(date[-1],"%Y-%m-%d")-datetime.strptime(date[0],"%Y-%m-%d")).days+1
  17.     total_days += last
  18.     print("%s ~ %s\t\t%s\t\t%d"%(date[0],date[1] if len(date)==2 else date[0], name[0],last))
  19. print("总天数:%d"%total_days)
复制代码

  1. 日期                                节假日                放假天数
  2. 2018-01-01 ~ 2018-01-01                元旦                1
  3. 2018-02-15 ~ 2018-02-21                春节                7
  4. 2018-04-05 ~ 2018-04-07                清明节                3
  5. 2018-04-29 ~ 2018-05-01                劳动节                3
  6. 2018-06-16 ~ 2018-06-18                端午节                3
  7. 2018-09-22 ~ 2018-09-24                中秋节                3
  8. 2018-10-01 ~ 2018-10-07                国庆日                7
  9. 总天数:27
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-28 20:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表