1. 前言
应某一瓜皮要求,为其写一个用于批量下载GNSS数据的脚本。恰好前几天研究过如何在教务系统中自动签到,便有了这篇博文,希望能够为下载数据的各位GNSSer提供一些参考。
2. 思路
- 使用selenium模块实现模拟登录,定位到下载数据的页面,并获取网页源码;
- 通过re模块(正则表达式)实现网页源码中数据压缩包名称的爬取;
- 匹配需要下载的测站和爬取得到的测站,提取能够下载的站点数据包名称;
- 根据站点数据包名称遍历下载。
3. Talk is cheap
运行环境:python3.7, Chrome(需要安装Chrome Driver)
1. 定义必要的参数,设置Chrome driver
# 用户自定义需要下载数据的时间
input_ = "2020-001"
# 设置需要下载测站的文件路径
bds_stas_dir = 'MultiGNSS.xlsx'
# 用户名和密码
username = " "
password = " "
# 定义驱动相关参数
options = webdriver.ChromeOptions()
## 禁用下载弹窗, 设置下载路径
prefs = {'profile.default_content_settings.popups': 0, 'download.default_directory': 'd:\\'}
options.add_experimental_option('prefs', prefs)
# 无窗口运行,初次运行建议有窗口运行(注释下行代码即可)
options.headless = True
# 设置浏览器驱动
driver = webdriver.Chrome(chrome_options=options)
2. 获取下载页面源代码
部分文件和对应的网页源码:
def get_source_code(driver, username, password):
driver.get("https://cddis.nasa.gov/archive/gnss/data/daily/")
time.sleep(2)
# 模拟登录
print("[Info] logging in ...")
driver.find_element_by_id("username").send_keys(username)
driver.find_element_by_id("password").send_keys(password)
driver.find_element_by_name("commit").click()
print("[Info] Finish logging!")
time.sleep(5)
driver.find_element_by_id(input_[:4]).click()
time.sleep(2)
driver.find_element_by_id(input_[5:8]).click()
time.sleep(2)
driver.find_element_by_id(input_[2:4] + "d").click()
time.sleep(2)
source = driver.page_source
return source
3. 正则表达式匹配
<a class="archiveItemText" id="ABMF00GLP_R_20200010000_01D_30S_MO.crx.gz"
title="DataFile" href="ABMF00GLP_R_20200010000_01D_30S_MO.crx.gz">
ABMF00GLP_R_20200010000_01D_30S_MO.crx.gz</a>
根据上面的源码爬取数据压缩包名称
pattern = re.compile('<a.*?id="(.*?)"\stitle="DataFile"')
items = re.findall(pattern, source)
部分爬取结果:
可以看到爬取到的数据压缩包名称以字符串的形式存在一个列表中。
4. 提取能够下载的站点数据包
由于需要下载的站点中有一部分在网站中不能找到,所以在下载前需要提取本地站点与网站提供下载站点重合的部分。
# 读取需要下载数据的站点名称;仅读取第一列,即站名
df = pd.read_excel(bds_stas_dir, sheet_name='BDS', usecols=[0])
# df.values为 numpy 数组
df_sta = df.values.tolist()
bds_sta_names = []
for sta in df_sta:
bds_sta_names.append(sta[0])
# 匹配一下需要下载的站点和网站中提供下载的站点,提取能够下载的站点数据压缩包名称
download_stas = []
for item in items:
if item[:9] in bds_sta_names:
download_stas.append(item)
5. 愉快的下载
# 遍历下载
print("[Info] Downloading...")
for id in tqdm(download_stas):
driver.find_element_by_id(id).click()
time.sleep(1)
print("[Info] Finish!")
下载过程截图:
4. 总结
虽然用的是最简单的方法,但是最终还是完成了大佬交代的任务。由于脚本没花太多时间写,没有考虑用其他复杂点的方法,所以仅供参考!