stock-tracker
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2019/9/30 13:58
|
||||
Desc:
|
||||
"""
|
||||
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/4/25 17:20
|
||||
Desc: 河北省空气质量预报信息发布系统
|
||||
https://110.249.223.67/publish
|
||||
每日 17 时发布
|
||||
等级划分
|
||||
1. 空气污染指数为0-50,空气质量级别为一级,空气质量状况属于优。此时,空气质量令人满意,基本无空气污染,各类人群可正常活动。
|
||||
2. 空气污染指数为51-100,空气质量级别为二级,空气质量状况属于良。此时空气质量可接受,但某些污染物可能对极少数异常敏感人群健康有较弱影响,建议极少数异常敏感人群应减少户外活动。
|
||||
3. 空气污染指数为101-150,空气质量级别为三级,空气质量状况属于轻度污染。此时,易感人群症状有轻度加剧,健康人群出现刺激症状。建议儿童、老年人及心脏病、呼吸系统疾病患者应减少长时间、高强度的户外锻炼。
|
||||
4. 空气污染指数为151-200,空气质量级别为四级,空气质量状况属于中度污染。此时,进一步加剧易感人群症状,可能对健康人群心脏、呼吸系统有影响,建议疾病患者避免长时间、高强度的户外锻练,一般人群适量减少户外运动。
|
||||
5. 空气污染指数为201-300,空气质量级别为五级,空气质量状况属于重度污染。此时,心脏病和肺病患者症状显著加剧,运动耐受力降低,健康人群普遍出现症状,建议儿童、老年人和心脏病、肺病患者应停留在室内,停止户外运动,一般人群减少户外运动。
|
||||
6. 空气污染指数大于300,空气质量级别为六级,空气质量状况属于严重污染。此时,健康人群运动耐受力降低,有明显强烈症状,提前出现某些疾病,建议儿童、老年人和病人应当留在室内,避免体力消耗,一般人群应避免户外活动。
|
||||
发布单位:河北省环境应急与重污染天气预警中心 技术支持:中国科学院大气物理研究所 中科三清科技有限公司
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
def air_quality_hebei() -> pd.DataFrame:
|
||||
"""
|
||||
河北省空气质量预报信息发布系统-空气质量预报, 未来 6 天
|
||||
http://218.11.10.130:8080/#/application/home
|
||||
:return: city = "", 返回所有地区的数据; city="唐山市", 返回唐山市的数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "http://218.11.10.130:8080/api/hour/130000.xml"
|
||||
r = requests.get(url)
|
||||
soup = BeautifulSoup(r.content, features="xml")
|
||||
data = []
|
||||
cities = soup.find_all("City")
|
||||
for city in cities:
|
||||
pointers = city.find_all("Pointer")
|
||||
for pointer in pointers:
|
||||
row = {
|
||||
"City": city.Name.text if city.Name else None,
|
||||
"Region": pointer.Region.text if pointer.Region else None,
|
||||
"Station": pointer.Name.text if pointer.Name else None,
|
||||
"DateTime": pointer.DataTime.text if pointer.DataTime else None,
|
||||
"AQI": pointer.AQI.text if pointer.AQI else None,
|
||||
"Level": pointer.Level.text if pointer.Level else None,
|
||||
"MaxPoll": pointer.MaxPoll.text if pointer.MaxPoll else None,
|
||||
"Longitude": pointer.CLng.text if pointer.CLng else None,
|
||||
"Latitude": pointer.CLat.text if pointer.CLat else None,
|
||||
}
|
||||
polls = pointer.find_all("Poll")
|
||||
for poll in polls:
|
||||
poll_name = poll.Name.text if poll.Name else None
|
||||
poll_value = poll.Value.text if poll.Value else None
|
||||
row[f"{poll_name}_Value"] = poll_value
|
||||
row[f"{poll_name}_IAQI"] = poll.IAQI.text if poll.IAQI else None
|
||||
data.append(row)
|
||||
|
||||
df = pd.DataFrame(data)
|
||||
numeric_columns = ["AQI", "Longitude", "Latitude"] + [
|
||||
col for col in df.columns if col.endswith("_Value") or col.endswith("_IAQI")
|
||||
]
|
||||
for col in numeric_columns:
|
||||
df[col] = pd.to_numeric(df[col], errors="coerce")
|
||||
|
||||
column_names = {
|
||||
"City": "城市",
|
||||
"Region": "区域",
|
||||
"Station": "监测点",
|
||||
"DateTime": "时间",
|
||||
"Level": "空气质量等级",
|
||||
"MaxPoll": "首要污染物",
|
||||
"Longitude": "经度",
|
||||
"Latitude": "纬度",
|
||||
"SO2_Value": "二氧化硫_浓度",
|
||||
"SO2_IAQI": "二氧化硫_IAQI",
|
||||
"CO_Value": "一氧化碳_浓度",
|
||||
"CO_IAQI": "一氧化碳_IAQI",
|
||||
"NO2_Value": "二氧化氮_浓度",
|
||||
"NO2_IAQI": "二氧化氮_IAQI",
|
||||
"O3-1H_Value": "臭氧1小时_浓度",
|
||||
"O3-1H_IAQI": "臭氧1小时_IAQI",
|
||||
"O3-8H_Value": "臭氧8小时_浓度",
|
||||
"O3-8H_IAQI": "臭氧8小时_IAQI",
|
||||
"PM2.5_Value": "PM2.5_浓度",
|
||||
"PM2.5_IAQI": "PM2.5_IAQI",
|
||||
"PM10_Value": "PM10_浓度",
|
||||
"PM10_IAQI": "PM10_IAQI",
|
||||
}
|
||||
df = df.rename(columns=column_names)
|
||||
basic_columns = [
|
||||
"城市",
|
||||
"区域",
|
||||
"监测点",
|
||||
"时间",
|
||||
"AQI",
|
||||
"空气质量等级",
|
||||
"首要污染物",
|
||||
"经度",
|
||||
"纬度",
|
||||
]
|
||||
pollutant_columns = [col for col in df.columns if col not in basic_columns]
|
||||
df = df[basic_columns + sorted(pollutant_columns)]
|
||||
return df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
air_quality_hebei_df = air_quality_hebei()
|
||||
print(air_quality_hebei_df)
|
||||
@@ -0,0 +1,294 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/4/2 22:40
|
||||
Desc: 真气网-空气质量
|
||||
https://www.zq12369.com/environment.php
|
||||
空气质量在线监测分析平台的空气质量数据
|
||||
https://www.aqistudy.cn/
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from io import StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from py_mini_racer import MiniRacer
|
||||
|
||||
from akshare.utils import demjson
|
||||
|
||||
|
||||
def _get_js_path(name: str = None, module_file: str = None) -> str:
|
||||
"""
|
||||
获取 JS 文件的路径(从模块所在目录查找)
|
||||
:param name: 文件名
|
||||
:type name: str
|
||||
:param module_file: 模块路径
|
||||
:type module_file: str
|
||||
:return: 路径
|
||||
:rtype: str
|
||||
"""
|
||||
module_folder = os.path.abspath(os.path.dirname(os.path.dirname(module_file)))
|
||||
module_json_path = os.path.join(module_folder, "air", name)
|
||||
return module_json_path
|
||||
|
||||
|
||||
def _get_file_content(file_name: str = "crypto.js") -> str:
|
||||
"""
|
||||
获取 JS 文件的内容
|
||||
:param file_name: JS 文件名
|
||||
:type file_name: str
|
||||
:return: 文件内容
|
||||
:rtype: str
|
||||
"""
|
||||
setting_file_name = file_name
|
||||
setting_file_path = _get_js_path(setting_file_name, __file__)
|
||||
with open(setting_file_path) as f:
|
||||
file_data = f.read()
|
||||
return file_data
|
||||
|
||||
|
||||
def has_month_data(href):
|
||||
"""
|
||||
Deal with href node
|
||||
:param href: href
|
||||
:type href: str
|
||||
:return: href result
|
||||
:rtype: str
|
||||
"""
|
||||
return href and re.compile("monthdata.php").search(href)
|
||||
|
||||
|
||||
def air_city_table() -> pd.DataFrame:
|
||||
"""
|
||||
真气网-空气质量历史数据查询-全部城市列表
|
||||
https://www.zq12369.com/environment.php?date=2019-06-05&tab=rank&order=DESC&type=DAY#rank
|
||||
:return: 城市映射
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
url = "https://www.zq12369.com/environment.php"
|
||||
date = "2020-05-01"
|
||||
temp_df = None
|
||||
if len(date.split("-")) == 3:
|
||||
params = {
|
||||
"date": date,
|
||||
"tab": "rank",
|
||||
"order": "DESC",
|
||||
"type": "DAY",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
temp_df = pd.read_html(StringIO(r.text))[1].iloc[1:, :]
|
||||
del temp_df["降序"]
|
||||
temp_df.reset_index(inplace=True)
|
||||
temp_df["index"] = temp_df.index + 1
|
||||
temp_df.columns = [
|
||||
"序号",
|
||||
"省份",
|
||||
"城市",
|
||||
"AQI",
|
||||
"空气质量",
|
||||
"PM2.5浓度",
|
||||
"首要污染物",
|
||||
]
|
||||
temp_df["AQI"] = pd.to_numeric(temp_df["AQI"])
|
||||
return temp_df
|
||||
|
||||
|
||||
def air_quality_watch_point(
|
||||
city: str = "杭州", start_date: str = "20220408", end_date: str = "20220409"
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
真气网-监测点空气质量-细化到具体城市的每个监测点
|
||||
指定之间段之间的空气质量数据
|
||||
https://www.zq12369.com/
|
||||
:param city: 调用 ak.air_city_table() 接口获取
|
||||
:type city: str
|
||||
:param start_date: e.g., "20190327"
|
||||
:type start_date: str
|
||||
:param end_date: e.g., ""20200327""
|
||||
:type end_date: str
|
||||
:return: 指定城市指定日期区间的观测点空气质量
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
start_date = "-".join([start_date[:4], start_date[4:6], start_date[6:]])
|
||||
end_date = "-".join([end_date[:4], end_date[4:6], end_date[6:]])
|
||||
url = "https://www.zq12369.com/api/zhenqiapi.php"
|
||||
file_data = _get_file_content(file_name="crypto.js")
|
||||
ctx = MiniRacer()
|
||||
ctx.eval(file_data)
|
||||
method = "GETCITYPOINTAVG"
|
||||
city_param = ctx.call("encode_param", city)
|
||||
payload = {
|
||||
"appId": "a01901d3caba1f362d69474674ce477f",
|
||||
"method": ctx.call("encode_param", method),
|
||||
"city": city_param,
|
||||
"startTime": ctx.call("encode_param", start_date),
|
||||
"endTime": ctx.call("encode_param", end_date),
|
||||
"secret": ctx.call("encode_secret", method, city_param, start_date, end_date),
|
||||
}
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/81.0.4044.122 Safari/537.36"
|
||||
}
|
||||
r = requests.post(url, data=payload, headers=headers)
|
||||
data_text = r.text
|
||||
data_json = demjson.decode(ctx.call("decode_result", data_text))
|
||||
temp_df = pd.DataFrame(data_json["rows"])
|
||||
return temp_df
|
||||
|
||||
|
||||
def air_quality_hist(
|
||||
city: str = "杭州",
|
||||
period: str = "day",
|
||||
start_date: str = "20190327",
|
||||
end_date: str = "20200427",
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
真气网-空气历史数据
|
||||
https://www.zq12369.com/
|
||||
:param city: 调用 ak.air_city_table() 接口获取所有城市列表
|
||||
:type city: str
|
||||
:param period: "hour": 每小时一个数据, 由于数据量比较大, 下载较慢; "day": 每天一个数据; "month": 每个月一个数据
|
||||
:type period: str
|
||||
:param start_date: e.g., "20190327"
|
||||
:type start_date: str
|
||||
:param end_date: e.g., "20200327"
|
||||
:type end_date: str
|
||||
:return: 指定城市和数据频率下在指定时间段内的空气质量数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
start_date = "-".join([start_date[:4], start_date[4:6], start_date[6:]])
|
||||
end_date = "-".join([end_date[:4], end_date[4:6], end_date[6:]])
|
||||
url = "https://www.zq12369.com/api/newzhenqiapi.php"
|
||||
file_data = _get_file_content(file_name="outcrypto.js")
|
||||
ctx = MiniRacer()
|
||||
ctx.eval(file_data)
|
||||
app_id = "4f0e3a273d547ce6b7147bfa7ceb4b6e"
|
||||
method = "CETCITYPERIOD"
|
||||
timestamp = ctx.eval("timestamp = new Date().getTime()")
|
||||
p_text = json.dumps(
|
||||
{
|
||||
"city": city,
|
||||
"endTime": f"{end_date} 23:45:39",
|
||||
"startTime": f"{start_date} 00:00:00",
|
||||
"type": period.upper(),
|
||||
},
|
||||
ensure_ascii=False,
|
||||
indent=None,
|
||||
).replace(' "', '"')
|
||||
secret = ctx.call("hex_md5", app_id + method + str(timestamp) + "WEB" + p_text)
|
||||
payload = {
|
||||
"appId": "4f0e3a273d547ce6b7147bfa7ceb4b6e",
|
||||
"method": "CETCITYPERIOD",
|
||||
"timestamp": int(timestamp),
|
||||
"clienttype": "WEB",
|
||||
"object": {
|
||||
"city": city,
|
||||
"type": period.upper(),
|
||||
"startTime": f"{start_date} 00:00:00",
|
||||
"endTime": f"{end_date} 23:45:39",
|
||||
},
|
||||
"secret": secret,
|
||||
}
|
||||
need = (
|
||||
json.dumps(payload, ensure_ascii=False, indent=None, sort_keys=False)
|
||||
.replace(' "', '"')
|
||||
.replace("\\", "")
|
||||
.replace('p": ', 'p":')
|
||||
.replace('t": ', 't":')
|
||||
)
|
||||
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"
|
||||
"Chrome/100.0.4896.75 Safari/537.36",
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
}
|
||||
params = {"param": ctx.call("encode_param", need)}
|
||||
r = requests.post(url, data=params, headers=headers)
|
||||
temp_text = ctx.call("decryptData", r.text)
|
||||
data_json = demjson.decode(ctx.call("b.decode", temp_text))
|
||||
temp_df = pd.DataFrame(data_json["result"]["data"]["rows"])
|
||||
temp_df.index = temp_df["time"]
|
||||
del temp_df["time"]
|
||||
temp_df = temp_df.astype(float, errors="ignore")
|
||||
return temp_df
|
||||
|
||||
|
||||
def air_quality_rank(date: str = "") -> pd.DataFrame:
|
||||
"""
|
||||
真气网-168 城市 AQI 排行榜
|
||||
https://www.zq12369.com/environment.php?date=2020-03-12&tab=rank&order=DESC&type=DAY#rank
|
||||
:param date: "": 当前时刻空气质量排名; "20200312": 当日空气质量排名; "202003": 当月空气质量排名; "2019": 当年空气质量排名;
|
||||
:type date: str
|
||||
:return: 指定 date 类型的空气质量排名数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
if len(date) == 4:
|
||||
date = date
|
||||
elif len(date) == 6:
|
||||
date = "-".join([date[:4], date[4:6]])
|
||||
elif date == "":
|
||||
date = "实时"
|
||||
else:
|
||||
date = "-".join([date[:4], date[4:6], date[6:]])
|
||||
|
||||
url = "https://www.zq12369.com/environment.php"
|
||||
|
||||
if len(date.split("-")) == 3:
|
||||
params = {
|
||||
"date": date,
|
||||
"tab": "rank",
|
||||
"order": "DESC",
|
||||
"type": "DAY",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
return pd.read_html(StringIO(r.text))[1].iloc[1:, :]
|
||||
elif len(date.split("-")) == 2:
|
||||
params = {
|
||||
"month": date,
|
||||
"tab": "rank",
|
||||
"order": "DESC",
|
||||
"type": "MONTH",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
return pd.read_html(StringIO(r.text))[2].iloc[1:, :]
|
||||
elif len(date.split("-")) == 1 and date != "实时":
|
||||
params = {
|
||||
"year": date,
|
||||
"tab": "rank",
|
||||
"order": "DESC",
|
||||
"type": "YEAR",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
return pd.read_html(StringIO(r.text))[3].iloc[1:, :]
|
||||
if date == "实时":
|
||||
params = {
|
||||
"tab": "rank",
|
||||
"order": "DESC",
|
||||
"type": "MONTH",
|
||||
}
|
||||
r = requests.get(url, params=params)
|
||||
return pd.read_html(StringIO(r.text))[0].iloc[1:, :]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
air_city_table_df = air_city_table()
|
||||
print(air_city_table_df)
|
||||
|
||||
air_quality_watch_point_df = air_quality_watch_point(
|
||||
city="杭州", start_date="20220408", end_date="20220409"
|
||||
)
|
||||
print(air_quality_watch_point_df)
|
||||
|
||||
air_quality_hist_df = air_quality_hist(
|
||||
city="北京",
|
||||
period="day",
|
||||
start_date="20220801",
|
||||
end_date="20240402",
|
||||
)
|
||||
print(air_quality_hist_df)
|
||||
|
||||
air_quality_rank_df = air_quality_rank()
|
||||
print(air_quality_rank_df)
|
||||
@@ -0,0 +1,413 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2019/11/25 20:45
|
||||
Desc: 空气质量接口配置文件
|
||||
"""
|
||||
|
||||
city_chinese_list = [
|
||||
"北京",
|
||||
"重庆",
|
||||
"福州",
|
||||
"广州",
|
||||
"杭州",
|
||||
"昆明",
|
||||
"南昌",
|
||||
"南京",
|
||||
"南宁",
|
||||
"南通",
|
||||
"宁波",
|
||||
"上海",
|
||||
"深圳",
|
||||
"苏州",
|
||||
"徐州",
|
||||
"银川",
|
||||
]
|
||||
|
||||
city_english_list = [
|
||||
"beijing",
|
||||
"chongqing",
|
||||
"foochow",
|
||||
"guangzhou",
|
||||
"hangzhou",
|
||||
"kunming",
|
||||
"nanchang",
|
||||
"nanjing",
|
||||
"nanning",
|
||||
"nantong",
|
||||
"ningbo",
|
||||
"shanghai",
|
||||
"shenzhen",
|
||||
"suzhou",
|
||||
"xuzhou",
|
||||
"yinchuan",
|
||||
]
|
||||
|
||||
city_code_dict = {
|
||||
"北京": "110000",
|
||||
"天津": "120000",
|
||||
"石家庄": "130100",
|
||||
"唐山": "130200",
|
||||
"秦皇岛": "130300",
|
||||
"邯郸": "130400",
|
||||
"邢台": "130500",
|
||||
"保定": "130600",
|
||||
"承德": "130800",
|
||||
"沧州": "130900",
|
||||
"廊坊": "131000",
|
||||
"衡水": "131100",
|
||||
"张家口": "131200",
|
||||
"太原": "140100",
|
||||
"大同": "140200",
|
||||
"阳泉": "140300",
|
||||
"长治": "140400",
|
||||
"晋城": "140500",
|
||||
"朔州": "140600",
|
||||
"晋中": "140700",
|
||||
"运城": "140800",
|
||||
"忻州": "140900",
|
||||
"临汾": "141000",
|
||||
"吕梁": "141100",
|
||||
"呼和浩特": "150100",
|
||||
"包头": "150200",
|
||||
"乌海": "150300",
|
||||
"赤峰": "150400",
|
||||
"通辽": "150500",
|
||||
"鄂尔多斯": "150600",
|
||||
"呼伦贝尔": "150700",
|
||||
"巴彦淖尔": "150800",
|
||||
"乌兰察布": "150900",
|
||||
"兴安盟": "152200",
|
||||
"锡林郭勒盟": "152500",
|
||||
"阿拉善盟": "152900",
|
||||
"沈阳": "210100",
|
||||
"大连": "210200",
|
||||
"瓦房店": "210281",
|
||||
"鞍山": "210300",
|
||||
"抚顺": "210400",
|
||||
"本溪": "210500",
|
||||
"丹东": "210600",
|
||||
"锦州": "210700",
|
||||
"营口": "210800",
|
||||
"阜新": "210900",
|
||||
"辽阳": "211000",
|
||||
"盘锦": "211100",
|
||||
"铁岭": "211200",
|
||||
"朝阳": "211300",
|
||||
"葫芦岛": "211400",
|
||||
"长春": "220100",
|
||||
"吉林": "220200",
|
||||
"四平": "220300",
|
||||
"辽源": "220400",
|
||||
"通化": "220500",
|
||||
"白山": "220600",
|
||||
"松原": "220700",
|
||||
"白城": "220800",
|
||||
"延边州": "222400",
|
||||
"哈尔滨": "230100",
|
||||
"齐齐哈尔": "230200",
|
||||
"鸡西": "230300",
|
||||
"鹤岗": "230400",
|
||||
"双鸭山": "230500",
|
||||
"大庆": "230600",
|
||||
"伊春": "230700",
|
||||
"佳木斯": "230800",
|
||||
"七台河": "230900",
|
||||
"牡丹江": "231000",
|
||||
"黑河": "231100",
|
||||
"绥化": "231200",
|
||||
"大兴安岭地区": "232700",
|
||||
"上海": "310000",
|
||||
"南京": "320100",
|
||||
"无锡": "320200",
|
||||
"江阴": "320281",
|
||||
"宜兴": "320282",
|
||||
"徐州": "320300",
|
||||
"常州": "320400",
|
||||
"溧阳": "320481",
|
||||
"金坛": "320482",
|
||||
"苏州": "320500",
|
||||
"常熟": "320581",
|
||||
"张家港": "320582",
|
||||
"昆山": "320583",
|
||||
"吴江": "320584",
|
||||
"太仓": "320585",
|
||||
"南通": "320600",
|
||||
"海门": "320684",
|
||||
"连云港": "320700",
|
||||
"淮安": "320800",
|
||||
"盐城": "320900",
|
||||
"扬州": "321000",
|
||||
"镇江": "321100",
|
||||
"句容": "321183",
|
||||
"泰州": "321200",
|
||||
"宿迁": "321300",
|
||||
"杭州": "330100",
|
||||
"富阳": "330183",
|
||||
"临安": "330185",
|
||||
"宁波": "330200",
|
||||
"温州": "330300",
|
||||
"嘉兴": "330400",
|
||||
"湖州": "330500",
|
||||
"诸暨": "330681",
|
||||
"金华": "330700",
|
||||
"义乌": "330782",
|
||||
"衢州": "330800",
|
||||
"舟山": "330900",
|
||||
"台州": "331000",
|
||||
"丽水": "331100",
|
||||
"绍兴": "331300",
|
||||
"合肥": "340100",
|
||||
"芜湖": "340200",
|
||||
"蚌埠": "340300",
|
||||
"淮南": "340400",
|
||||
"马鞍山": "340500",
|
||||
"淮北": "340600",
|
||||
"铜陵": "340700",
|
||||
"安庆": "340800",
|
||||
"黄山": "341000",
|
||||
"滁州": "341100",
|
||||
"阜阳": "341200",
|
||||
"宿州": "341300",
|
||||
"六安": "341500",
|
||||
"亳州": "341600",
|
||||
"池州": "341700",
|
||||
"宣城": "341800",
|
||||
"福州": "350100",
|
||||
"厦门": "350200",
|
||||
"莆田": "350300",
|
||||
"三明": "350400",
|
||||
"泉州": "350500",
|
||||
"漳州": "350600",
|
||||
"南平": "350700",
|
||||
"龙岩": "350800",
|
||||
"宁德": "350900",
|
||||
"南昌": "360100",
|
||||
"景德镇": "360200",
|
||||
"萍乡": "360300",
|
||||
"九江": "360400",
|
||||
"新余": "360500",
|
||||
"鹰潭": "360600",
|
||||
"赣州": "360700",
|
||||
"吉安": "360800",
|
||||
"宜春": "360900",
|
||||
"抚州": "361000",
|
||||
"上饶": "361100",
|
||||
"济南": "370100",
|
||||
"章丘": "370181",
|
||||
"青岛": "370200",
|
||||
"胶州": "370281",
|
||||
"即墨": "370282",
|
||||
"平度": "370283",
|
||||
"胶南": "370284",
|
||||
"莱西": "370285",
|
||||
"淄博": "370300",
|
||||
"枣庄": "370400",
|
||||
"东营": "370500",
|
||||
"烟台": "370600",
|
||||
"莱州": "370683",
|
||||
"蓬莱": "370684",
|
||||
"招远": "370685",
|
||||
"潍坊": "370700",
|
||||
"寿光": "370783",
|
||||
"济宁": "370800",
|
||||
"泰安": "370900",
|
||||
"威海": "371000",
|
||||
"文登": "371081",
|
||||
"荣成": "371082",
|
||||
"乳山": "371083",
|
||||
"日照": "371100",
|
||||
"莱芜": "371200",
|
||||
"临沂": "371300",
|
||||
"德州": "371400",
|
||||
"聊城": "371500",
|
||||
"滨州": "371600",
|
||||
"菏泽": "371700",
|
||||
"郑州": "410100",
|
||||
"开封": "410200",
|
||||
"洛阳": "410300",
|
||||
"平顶山": "410400",
|
||||
"安阳": "410500",
|
||||
"鹤壁": "410600",
|
||||
"新乡": "410700",
|
||||
"焦作": "410800",
|
||||
"濮阳": "410900",
|
||||
"许昌": "411000",
|
||||
"漯河": "411100",
|
||||
"三门峡": "411200",
|
||||
"南阳": "411300",
|
||||
"商丘": "411400",
|
||||
"信阳": "411500",
|
||||
"周口": "411600",
|
||||
"驻马店": "411700",
|
||||
"武汉": "420100",
|
||||
"黄石": "420200",
|
||||
"十堰": "420300",
|
||||
"宜昌": "420500",
|
||||
"襄阳": "420600",
|
||||
"鄂州": "420700",
|
||||
"荆门": "420800",
|
||||
"孝感": "420900",
|
||||
"荆州": "421000",
|
||||
"黄冈": "421100",
|
||||
"咸宁": "421200",
|
||||
"随州": "421300",
|
||||
"恩施州": "422800",
|
||||
"长沙": "430100",
|
||||
"株洲": "430200",
|
||||
"湘潭": "430300",
|
||||
"衡阳": "430400",
|
||||
"邵阳": "430500",
|
||||
"岳阳": "430600",
|
||||
"常德": "430700",
|
||||
"张家界": "430800",
|
||||
"益阳": "430900",
|
||||
"郴州": "431000",
|
||||
"永州": "431100",
|
||||
"怀化": "431200",
|
||||
"娄底": "431300",
|
||||
"湘西州": "433100",
|
||||
"广州": "440100",
|
||||
"韶关": "440200",
|
||||
"深圳": "440300",
|
||||
"珠海": "440400",
|
||||
"汕头": "440500",
|
||||
"佛山": "440600",
|
||||
"江门": "440700",
|
||||
"湛江": "440800",
|
||||
"茂名": "440900",
|
||||
"肇庆": "441200",
|
||||
"惠州": "441300",
|
||||
"梅州": "441400",
|
||||
"汕尾": "441500",
|
||||
"河源": "441600",
|
||||
"阳江": "441700",
|
||||
"清远": "441800",
|
||||
"东莞": "441900",
|
||||
"中山": "442000",
|
||||
"潮州": "445100",
|
||||
"揭阳": "445200",
|
||||
"云浮": "445300",
|
||||
"南宁": "450100",
|
||||
"柳州": "450200",
|
||||
"桂林": "450300",
|
||||
"梧州": "450400",
|
||||
"北海": "450500",
|
||||
"防城港": "450600",
|
||||
"钦州": "450700",
|
||||
"贵港": "450800",
|
||||
"玉林": "450900",
|
||||
"百色": "451000",
|
||||
"贺州": "451100",
|
||||
"河池": "451200",
|
||||
"来宾": "451300",
|
||||
"崇左": "451400",
|
||||
"海口": "460100",
|
||||
"三亚": "460200",
|
||||
"重庆": "500000",
|
||||
"成都": "510100",
|
||||
"自贡": "510300",
|
||||
"攀枝花": "510400",
|
||||
"泸州": "510500",
|
||||
"德阳": "510600",
|
||||
"绵阳": "510700",
|
||||
"广元": "510800",
|
||||
"遂宁": "510900",
|
||||
"内江": "511000",
|
||||
"乐山": "511100",
|
||||
"南充": "511300",
|
||||
"眉山": "511400",
|
||||
"宜宾": "511500",
|
||||
"广安": "511600",
|
||||
"达州": "511700",
|
||||
"雅安": "511800",
|
||||
"巴中": "511900",
|
||||
"资阳": "512000",
|
||||
"阿坝州": "513200",
|
||||
"甘孜州": "513300",
|
||||
"凉山州": "513400",
|
||||
"贵阳": "520100",
|
||||
"六盘水": "520200",
|
||||
"遵义": "520300",
|
||||
"安顺": "520400",
|
||||
"铜仁地区": "522200",
|
||||
"黔西南州": "522300",
|
||||
"毕节": "522400",
|
||||
"黔东南州": "522600",
|
||||
"黔南州": "522700",
|
||||
"昆明": "530100",
|
||||
"曲靖": "530300",
|
||||
"玉溪": "530400",
|
||||
"保山": "530500",
|
||||
"昭通": "530600",
|
||||
"丽江": "530700",
|
||||
"普洱": "530800",
|
||||
"临沧": "530900",
|
||||
"红河州": "532522",
|
||||
"文山州": "532621",
|
||||
"西双版纳州": "532801",
|
||||
"大理州": "532901",
|
||||
"德宏州": "533103",
|
||||
"怒江州": "533300",
|
||||
"迪庆州": "533421",
|
||||
"拉萨": "540100",
|
||||
"昌都": "542100",
|
||||
"山南": "542200",
|
||||
"日喀则": "542300",
|
||||
"那曲地区": "542400",
|
||||
"阿里地区": "542500",
|
||||
"林芝": "542600",
|
||||
"西安": "610100",
|
||||
"铜川": "610200",
|
||||
"宝鸡": "610300",
|
||||
"咸阳": "610400",
|
||||
"渭南": "610500",
|
||||
"延安": "610600",
|
||||
"汉中": "610700",
|
||||
"榆林": "610800",
|
||||
"安康": "610900",
|
||||
"商洛": "611000",
|
||||
"兰州": "620100",
|
||||
"嘉峪关": "620200",
|
||||
"金昌": "620300",
|
||||
"白银": "620400",
|
||||
"天水": "620500",
|
||||
"武威": "620600",
|
||||
"张掖": "620700",
|
||||
"平凉": "620800",
|
||||
"酒泉": "620900",
|
||||
"庆阳": "621000",
|
||||
"定西": "621100",
|
||||
"陇南": "621200",
|
||||
"临夏州": "622900",
|
||||
"甘南州": "623000",
|
||||
"西宁": "630100",
|
||||
"海东地区": "632100",
|
||||
"海北州": "632200",
|
||||
"黄南州": "632300",
|
||||
"海南州": "632500",
|
||||
"果洛州": "632600",
|
||||
"玉树州": "632700",
|
||||
"海西州": "632800",
|
||||
"银川": "640100",
|
||||
"石嘴山": "640200",
|
||||
"吴忠": "640300",
|
||||
"固原": "640400",
|
||||
"中卫": "640500",
|
||||
"乌鲁木齐": "650100",
|
||||
"克拉玛依": "650200",
|
||||
"吐鲁番地区": "652100",
|
||||
"哈密地区": "652200",
|
||||
"昌吉州": "652300",
|
||||
"博州": "652700",
|
||||
"库尔勒": "652800",
|
||||
"阿克苏地区": "652900",
|
||||
"克州": "653000",
|
||||
"喀什地区": "653100",
|
||||
"和田地区": "653200",
|
||||
"伊犁哈萨克州": "654000",
|
||||
"塔城地区": "654200",
|
||||
"阿勒泰地区": "654300",
|
||||
"石河子": "659001",
|
||||
"五家渠": "659004",
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
function Base64() {
|
||||
_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", this.encode = function(a) {
|
||||
var c, d, e, f, g, h, i, b = "",
|
||||
j = 0;
|
||||
for (a = _utf8_encode(a); j < a.length;) c = a.charCodeAt(j++), d = a.charCodeAt(j++), e = a.charCodeAt(j++), f = c >> 2, g = (3 & c) << 4 | d >> 4, h = (15 & d) << 2 | e >> 6, i = 63 & e, isNaN(d) ? h = i = 64 : isNaN(e) && (i = 64), b = b + _keyStr.charAt(f) + _keyStr.charAt(g) + _keyStr.charAt(h) + _keyStr.charAt(i);
|
||||
return b
|
||||
}, this.decode = function(a) {
|
||||
var c, d, e, f, g, h, i, b = "",
|
||||
j = 0;
|
||||
for (a = a.replace(/[^A-Za-z0-9\+\/\=]/g, ""); j < a.length;) f = _keyStr.indexOf(a.charAt(j++)), g = _keyStr.indexOf(a.charAt(j++)), h = _keyStr.indexOf(a.charAt(j++)), i = _keyStr.indexOf(a.charAt(j++)), c = f << 2 | g >> 4, d = (15 & g) << 4 | h >> 2, e = (3 & h) << 6 | i, b += String.fromCharCode(c), 64 != h && (b += String.fromCharCode(d)), 64 != i && (b += String.fromCharCode(e));
|
||||
return b = _utf8_decode(b)
|
||||
}, _utf8_encode = function(a) {
|
||||
var b, c, d;
|
||||
for (a = a.replace(/\r\n/g, "\n"), b = "", c = 0; c < a.length; c++) d = a.charCodeAt(c), 128 > d ? b += String.fromCharCode(d) : d > 127 && 2048 > d ? (b += String.fromCharCode(192 | d >> 6), b += String.fromCharCode(128 | 63 & d)) : (b += String.fromCharCode(224 | d >> 12), b += String.fromCharCode(128 | 63 & d >> 6), b += String.fromCharCode(128 | 63 & d));
|
||||
return b
|
||||
}, _utf8_decode = function(a) {
|
||||
for (var b = "", c = 0, d = c1 = c2 = 0; c < a.length;) d = a.charCodeAt(c), 128 > d ? (b += String.fromCharCode(d), c++) : d > 191 && 224 > d ? (c2 = a.charCodeAt(c + 1), b += String.fromCharCode((31 & d) << 6 | 63 & c2), c += 2) : (c2 = a.charCodeAt(c + 1), c3 = a.charCodeAt(c + 2), b += String.fromCharCode((15 & d) << 12 | (63 & c2) << 6 | 63 & c3), c += 3);
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
function hex_md5(a) {
|
||||
return binl2hex(core_md5(str2binl(a), a.length * chrsz))
|
||||
}
|
||||
|
||||
function b64_md5(a) {
|
||||
return binl2b64(core_md5(str2binl(a), a.length * chrsz))
|
||||
}
|
||||
|
||||
function str_md5(a) {
|
||||
return binl2str(core_md5(str2binl(a), a.length * chrsz))
|
||||
}
|
||||
|
||||
function hex_hmac_md5(a, b) {
|
||||
return binl2hex(core_hmac_md5(a, b))
|
||||
}
|
||||
|
||||
function b64_hmac_md5(a, b) {
|
||||
return binl2b64(core_hmac_md5(a, b))
|
||||
}
|
||||
|
||||
function str_hmac_md5(a, b) {
|
||||
return binl2str(core_hmac_md5(a, b))
|
||||
}
|
||||
|
||||
function md5_vm_test() {
|
||||
return "900150983cd24fb0d6963f7d28e17f72" == hex_md5("abc")
|
||||
}
|
||||
|
||||
function core_md5(a, b) {
|
||||
var c, d, e, f, g, h, i, j, k;
|
||||
for (a[b >> 5] |= 128 << b % 32, a[(b + 64 >>> 9 << 4) + 14] = b, c = 1732584193, d = -271733879, e = -1732584194, f = 271733878, g = 0; g < a.length; g += 16) h = c, i = d, j = e, k = f, c = md5_ff(c, d, e, f, a[g + 0], 7, -680876936), f = md5_ff(f, c, d, e, a[g + 1], 12, -389564586), e = md5_ff(e, f, c, d, a[g + 2], 17, 606105819), d = md5_ff(d, e, f, c, a[g + 3], 22, -1044525330), c = md5_ff(c, d, e, f, a[g + 4], 7, -176418897), f = md5_ff(f, c, d, e, a[g + 5], 12, 1200080426), e = md5_ff(e, f, c, d, a[g + 6], 17, -1473231341), d = md5_ff(d, e, f, c, a[g + 7], 22, -45705983), c = md5_ff(c, d, e, f, a[g + 8], 7, 1770035416), f = md5_ff(f, c, d, e, a[g + 9], 12, -1958414417), e = md5_ff(e, f, c, d, a[g + 10], 17, -42063), d = md5_ff(d, e, f, c, a[g + 11], 22, -1990404162), c = md5_ff(c, d, e, f, a[g + 12], 7, 1804603682), f = md5_ff(f, c, d, e, a[g + 13], 12, -40341101), e = md5_ff(e, f, c, d, a[g + 14], 17, -1502002290), d = md5_ff(d, e, f, c, a[g + 15], 22, 1236535329), c = md5_gg(c, d, e, f, a[g + 1], 5, -165796510), f = md5_gg(f, c, d, e, a[g + 6], 9, -1069501632), e = md5_gg(e, f, c, d, a[g + 11], 14, 643717713), d = md5_gg(d, e, f, c, a[g + 0], 20, -373897302), c = md5_gg(c, d, e, f, a[g + 5], 5, -701558691), f = md5_gg(f, c, d, e, a[g + 10], 9, 38016083), e = md5_gg(e, f, c, d, a[g + 15], 14, -660478335), d = md5_gg(d, e, f, c, a[g + 4], 20, -405537848), c = md5_gg(c, d, e, f, a[g + 9], 5, 568446438), f = md5_gg(f, c, d, e, a[g + 14], 9, -1019803690), e = md5_gg(e, f, c, d, a[g + 3], 14, -187363961), d = md5_gg(d, e, f, c, a[g + 8], 20, 1163531501), c = md5_gg(c, d, e, f, a[g + 13], 5, -1444681467), f = md5_gg(f, c, d, e, a[g + 2], 9, -51403784), e = md5_gg(e, f, c, d, a[g + 7], 14, 1735328473), d = md5_gg(d, e, f, c, a[g + 12], 20, -1926607734), c = md5_hh(c, d, e, f, a[g + 5], 4, -378558), f = md5_hh(f, c, d, e, a[g + 8], 11, -2022574463), e = md5_hh(e, f, c, d, a[g + 11], 16, 1839030562), d = md5_hh(d, e, f, c, a[g + 14], 23, -35309556), c = md5_hh(c, d, e, f, a[g + 1], 4, -1530992060), f = md5_hh(f, c, d, e, a[g + 4], 11, 1272893353), e = md5_hh(e, f, c, d, a[g + 7], 16, -155497632), d = md5_hh(d, e, f, c, a[g + 10], 23, -1094730640), c = md5_hh(c, d, e, f, a[g + 13], 4, 681279174), f = md5_hh(f, c, d, e, a[g + 0], 11, -358537222), e = md5_hh(e, f, c, d, a[g + 3], 16, -722521979), d = md5_hh(d, e, f, c, a[g + 6], 23, 76029189), c = md5_hh(c, d, e, f, a[g + 9], 4, -640364487), f = md5_hh(f, c, d, e, a[g + 12], 11, -421815835), e = md5_hh(e, f, c, d, a[g + 15], 16, 530742520), d = md5_hh(d, e, f, c, a[g + 2], 23, -995338651), c = md5_ii(c, d, e, f, a[g + 0], 6, -198630844), f = md5_ii(f, c, d, e, a[g + 7], 10, 1126891415), e = md5_ii(e, f, c, d, a[g + 14], 15, -1416354905), d = md5_ii(d, e, f, c, a[g + 5], 21, -57434055), c = md5_ii(c, d, e, f, a[g + 12], 6, 1700485571), f = md5_ii(f, c, d, e, a[g + 3], 10, -1894986606), e = md5_ii(e, f, c, d, a[g + 10], 15, -1051523), d = md5_ii(d, e, f, c, a[g + 1], 21, -2054922799), c = md5_ii(c, d, e, f, a[g + 8], 6, 1873313359), f = md5_ii(f, c, d, e, a[g + 15], 10, -30611744), e = md5_ii(e, f, c, d, a[g + 6], 15, -1560198380), d = md5_ii(d, e, f, c, a[g + 13], 21, 1309151649), c = md5_ii(c, d, e, f, a[g + 4], 6, -145523070), f = md5_ii(f, c, d, e, a[g + 11], 10, -1120210379), e = md5_ii(e, f, c, d, a[g + 2], 15, 718787259), d = md5_ii(d, e, f, c, a[g + 9], 21, -343485551), c = safe_add(c, h), d = safe_add(d, i), e = safe_add(e, j), f = safe_add(f, k);
|
||||
return Array(c, d, e, f)
|
||||
}
|
||||
|
||||
function md5_cmn(a, b, c, d, e, f) {
|
||||
return safe_add(bit_rol(safe_add(safe_add(b, a), safe_add(d, f)), e), c)
|
||||
}
|
||||
|
||||
function md5_ff(a, b, c, d, e, f, g) {
|
||||
return md5_cmn(b & c | ~b & d, a, b, e, f, g)
|
||||
}
|
||||
|
||||
function md5_gg(a, b, c, d, e, f, g) {
|
||||
return md5_cmn(b & d | c & ~d, a, b, e, f, g)
|
||||
}
|
||||
|
||||
function md5_hh(a, b, c, d, e, f, g) {
|
||||
return md5_cmn(b ^ c ^ d, a, b, e, f, g)
|
||||
}
|
||||
|
||||
function md5_ii(a, b, c, d, e, f, g) {
|
||||
return md5_cmn(c ^ (b | ~d), a, b, e, f, g)
|
||||
}
|
||||
|
||||
function core_hmac_md5(a, b) {
|
||||
var d, e, f, g, c = str2binl(a);
|
||||
for (c.length > 16 && (c = core_md5(c, a.length * chrsz)), d = Array(16), e = Array(16), f = 0; 16 > f; f++) d[f] = 909522486 ^ c[f], e[f] = 1549556828 ^ c[f];
|
||||
return g = core_md5(d.concat(str2binl(b)), 512 + b.length * chrsz), core_md5(e.concat(g), 640)
|
||||
}
|
||||
|
||||
function safe_add(a, b) {
|
||||
var c = (65535 & a) + (65535 & b),
|
||||
d = (a >> 16) + (b >> 16) + (c >> 16);
|
||||
return d << 16 | 65535 & c
|
||||
}
|
||||
|
||||
function bit_rol(a, b) {
|
||||
return a << b | a >>> 32 - b
|
||||
}
|
||||
|
||||
function str2binl(a) {
|
||||
var d, b = Array(),
|
||||
c = (1 << chrsz) - 1;
|
||||
for (d = 0; d < a.length * chrsz; d += chrsz) b[d >> 5] |= (a.charCodeAt(d / chrsz) & c) << d % 32;
|
||||
return b
|
||||
}
|
||||
|
||||
function binl2str(a) {
|
||||
var d, b = "",
|
||||
c = (1 << chrsz) - 1;
|
||||
for (d = 0; d < 32 * a.length; d += chrsz) b += String.fromCharCode(a[d >> 5] >>> d % 32 & c);
|
||||
return b
|
||||
}
|
||||
|
||||
function binl2hex(a) {
|
||||
var d, b = hexcase ? "0123456789ABCDEF" : "0123456789abcdef",
|
||||
c = "";
|
||||
for (d = 0; d < 4 * a.length; d++) c += b.charAt(15 & a[d >> 2] >> 8 * (d % 4) + 4) + b.charAt(15 & a[d >> 2] >> 8 * (d % 4));
|
||||
return c
|
||||
}
|
||||
|
||||
function binl2b64(a) {
|
||||
var d, e, f, b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
|
||||
c = "";
|
||||
for (d = 0; d < 4 * a.length; d += 3)
|
||||
for (e = (255 & a[d >> 2] >> 8 * (d % 4)) << 16 | (255 & a[d + 1 >> 2] >> 8 * ((d + 1) % 4)) << 8 | 255 & a[d + 2 >> 2] >> 8 * ((d + 2) % 4), f = 0; 4 > f; f++) c += 8 * d + 6 * f > 32 * a.length ? b64pad : b.charAt(63 & e >> 6 * (3 - f));
|
||||
return c
|
||||
}
|
||||
|
||||
function encode_param(a) {
|
||||
var b = new Base64;
|
||||
return b.encode(a)
|
||||
}
|
||||
|
||||
function encode_secret() {
|
||||
var b, a = appId;
|
||||
for (b = 0; b < arguments.length; b++) a += arguments[b];
|
||||
return a = a.replace(/\s/g, ""), hex_md5(a)
|
||||
}
|
||||
|
||||
function decode_result(a) {
|
||||
var b = new Base64;
|
||||
return b.decode(b.decode(b.decode(a)))
|
||||
}
|
||||
var hexcase = 0,
|
||||
b64pad = "",
|
||||
chrsz = 8,
|
||||
appId = "a01901d3caba1f362d69474674ce477f";
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Date: 2024/4/29 16:00
|
||||
Desc: 日出和日落数据
|
||||
https://www.timeanddate.com
|
||||
"""
|
||||
|
||||
from io import StringIO
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
|
||||
def sunrise_city_list() -> list:
|
||||
"""
|
||||
查询日出与日落数据的城市列表
|
||||
https://www.timeanddate.com/astronomy/china
|
||||
:return: 所有可以获取的数据的城市列表
|
||||
:rtype: list
|
||||
"""
|
||||
url = "https://www.timeanddate.com/astronomy/china"
|
||||
r = requests.get(url)
|
||||
city_list = []
|
||||
china_city_one_df = pd.read_html(StringIO(r.text))[1]
|
||||
china_city_two_df = pd.read_html(StringIO(r.text))[2]
|
||||
city_list.extend([item.lower() for item in china_city_one_df.iloc[:, 0].tolist()])
|
||||
city_list.extend([item.lower() for item in china_city_one_df.iloc[:, 3].tolist()])
|
||||
city_list.extend([item.lower() for item in china_city_one_df.iloc[:, 6].tolist()])
|
||||
city_list.extend([item.lower() for item in china_city_two_df.iloc[:, 0].tolist()])
|
||||
city_list.extend([item.lower() for item in china_city_two_df.iloc[:, 1].tolist()])
|
||||
city_list.extend([item.lower() for item in china_city_two_df.iloc[:, 2].tolist()])
|
||||
city_list.extend([item.lower() for item in china_city_two_df.iloc[:, 3].tolist()])
|
||||
city_list.extend(
|
||||
[item.lower() for item in china_city_two_df.iloc[:, 4].dropna().tolist()]
|
||||
)
|
||||
return city_list
|
||||
|
||||
|
||||
def sunrise_daily(date: str = "20240428", city: str = "beijing") -> pd.DataFrame:
|
||||
"""
|
||||
每日日出日落数据
|
||||
https://www.timeanddate.com/astronomy/china/shaoxing
|
||||
:param date: 需要查询的日期, e.g., “20200428”
|
||||
:type date: str
|
||||
:param city: 需要查询的城市; 注意输入的格式, e.g., "北京", "上海"
|
||||
:type city: str
|
||||
:return: 返回指定日期指定地区的日出日落数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings()
|
||||
if city in sunrise_city_list():
|
||||
year = date[:4]
|
||||
month = date[4:6]
|
||||
url = f"https://www.timeanddate.com/sun/china/{city}?month={month}&year={year}"
|
||||
r = requests.get(url, verify=False)
|
||||
table = pd.read_html(StringIO(r.text), header=2)[1]
|
||||
month_df = table.iloc[:-1,]
|
||||
day_df = month_df[
|
||||
month_df.iloc[:, 0].astype(str).str.zfill(2) == date[6:]
|
||||
].copy()
|
||||
day_df.index = pd.to_datetime([date] * len(day_df), format="%Y%m%d")
|
||||
day_df.reset_index(inplace=True)
|
||||
day_df.rename(columns={"index": "date"}, inplace=True)
|
||||
day_df["date"] = pd.to_datetime(day_df["date"]).dt.date
|
||||
return day_df
|
||||
else:
|
||||
raise "请输入正确的城市名称"
|
||||
|
||||
|
||||
def sunrise_monthly(date: str = "20240428", city: str = "beijing") -> pd.DataFrame:
|
||||
"""
|
||||
每个指定 date 所在月份的每日日出日落数据, 如果当前月份未到月底, 则以预测值填充
|
||||
https://www.timeanddate.com/astronomy/china/shaoxing
|
||||
:param date: 需要查询的日期, 这里用来指定 date 所在的月份; e.g., “20200428”
|
||||
:type date: str
|
||||
:param city: 需要查询的城市; 注意输入的格式, e.g., "北京", "上海"
|
||||
:type city: str
|
||||
:return: 指定 date 所在月份的每日日出日落数据
|
||||
:rtype: pandas.DataFrame
|
||||
"""
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings()
|
||||
if city in sunrise_city_list():
|
||||
year = date[:4]
|
||||
month = date[4:6]
|
||||
url = f"https://www.timeanddate.com/sun/china/{city}?month={month}&year={year}"
|
||||
r = requests.get(url)
|
||||
table = pd.read_html(StringIO(r.text), header=2)[1]
|
||||
month_df = table.iloc[:-1,].copy()
|
||||
month_df.index = [date[:-2]] * len(month_df)
|
||||
month_df.reset_index(inplace=True)
|
||||
month_df.rename(
|
||||
columns={
|
||||
"index": "date",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
return month_df
|
||||
else:
|
||||
raise "请输入正确的城市名称"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sunrise_daily_df = sunrise_daily(date="20240428", city="beijing")
|
||||
print(sunrise_daily_df)
|
||||
|
||||
sunrise_monthly_df = sunrise_monthly(date="20240428", city="beijing")
|
||||
print(sunrise_monthly_df)
|
||||
Reference in New Issue
Block a user