概述
3月的中旬时候参与了学校的一个大创项目,作为本科生,本人只是摸鱼打杂,负责了其中的一个功能模块:爬取NASA Modis数据。
整个过程也只是慢慢修改增添方案,主体功能于四月中旬基本完成。因为后续并未真正用到,所以自己还没进行更多优化,请各位谅解。如个人使用参考,可以试试这个爬虫。(2021年3-5月期间的,最近没留意网站更新)
整个过程中,可以收获对Cookie、python的selenium库以及基本爬虫知识的一定了解(也是我自己学到的一些东西)。
需求分析
如图,上框为用户浏览网页时见到的URL,中间位置的框依次为产品号,日期范围,区域经纬度范围,下框为筛选条件下的目标文件。
可见,使用者可以根据不同条件筛选产品。
中间URL:
Request Headers(其中最重要的是Cookie!所以需要想办法获取!):
从Preview页面可以看到下载URL及相关信息,访问下载URL并进行下载需要登陆或通过Cookie:
基本思路
代码
nasa_moids.py:
目前还未采用Scrapy下载(获得Cookie和下载URL后),后续可以考虑以此为优化角度。
import requests
import json
import os
import random
import time
import datetime
from dateutil.relativedelta import relativedelta
import autoClick
__author__ = 'Ray'
'''
Task:输入产品信息,附加筛选条件,自动爬取Modis遥感数据
观察/记录:
1.数据一般延时更新,且所选区域在部分日期下没有数据
2.仅hdf所在URL需要cookies,所以应模拟登录获取Cookies(其实短期内Cookies不变,如果不要求过高,可以手动输入Cookies)
3.要用到中间URL,找规律
Tips:
1.网络事先需要连接好,并保持稳定,否则不只会影响模拟点击。(看到一种说法是借助浏览器厂商差异,换FireFox,还未尝试)
2.Modis网站的服务器运行状况良好
3.解决访问时间过长,模拟点击报错问题!(循环尝试?),下载URL卡死问题
4.目前的访问和下载速度较慢,考虑异步,多线程下载或其他方式
5.ban,代理池,访问频率(考虑要不要定期清除Cookie)
6.符合使用需求
7.后续维护问题,观察网站变化,也要靠考虑浏览器版本升级与驱动的兼容
'''
class Nasa: # 面向对象编程,创建类
def __init__(self):
self.headers1 = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36",
'Referer': 'https://ladsweb.modaps.eosdis.nasa.gov/search/order/4/MOD11A1--6/2021-02-22..2021-03-08/DB/97,30.1,107.1,21.2',
'Host': 'ladsweb.modaps.eosdis.nasa.gov',
'Accept': '*/*',
'Connection': 'keep-alive',
'X-Requested-With': 'XMLHttpRequest'}
# 还未修改Referer!!
# 留意下headers会不会变化
# 当遇到403时,headers的内容越全越有希望,除了在get()方法中添加cookies参数,也可以在headers字典中添加cookies
self.headers2 = {
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3"}
# 获取当前日期范围
def getDate(self, if_range='last month', range=20):
# example: '2021-02-22..2021-03-08'
date = time.strftime('%Y-%m-%d', time.localtime())
# 如果是范围筛选,还要考虑年份和月份的灵活变化
if if_range == 'all':
date = '2020-01-01..' + date
else:
date = str(datetime.date.today() + relativedelta(days=-30)) + '..' + str(date)
print('Date range:' + str(date) + '\n')
return date
# 获取页面
def getPage(self, url, cookie=None):
try:
re = requests.get(url, headers=self.headers1, timeout=(9.05, 6.05), cookies=cookie)
print('已完成get指令')
print(re.status_code)
re.raise_for_status()
re.encoding = re.apparent_encoding
print('获取页面成功!准备return')
# time.sleep(1)
return re
except requests.exceptions.RequestException as e:
print(e)
print('请求失败!您的网络状况可能存在一点问题,需重试')
# 将开发者工具界面中,Headers里显示的cookie转换为字典
def cookieToDict(self, cookie):
cookie = cookie.split(';')
cok = dict()
for i in cookie:
part = i.split('=')
part[0] = part[0].strip(' ')
cok