102302141_易敏亮第二次数据采集作业

课程链接 https://edu.cnblogs.com/campus/fzu/2025DataCollectionandFusiontechnology
作业链接 https://gitee.com/lisu6/data_collect/tree/master/2
作业1气象网链接 https://gitee.com/lisu6/data_collect/tree/master/2/wearth
作业2东方财富链接 https://gitee.com/lisu6/data_collect/tree/master/2/east_money
作业3大学排名链接 https://gitee.com/lisu6/data_collect/tree/master/2/rank2
学号姓名 102302141 易敏亮

作业①:

要求:在中国气象网(http://www.weather.com.cn)给定城市集的7日天气预报,并保存在数据库。

简介:
通过F12网络功能查找关键元素“晴转多云”,快速定位数据所在,发现在' https://www.weather.com.cn/weather/101010100.shtml '异步加载,观察发现不同城市数据映射url的字符串相同。
通过查找发现' https://j.i8tq.com/weather2020/search/city.js '中存储了城市->字符串映射关系,且为标准字典,可根据其查询。

心得:
深刻体会到逆向思维在数据采集中的重要性——从页面显示的"晴转多云"等关键词出发,通过浏览器开发者工具反向追踪数据源,成功定位到隐藏的异步接口和城市编码映射文件。这不仅揭示了网页表面结构与真实数据源的差异,更让我认识到动态网站的数据往往通过API异步加载,直接分析网络请求比解析静态HTML更能高效获取结构化数据。
image
image

def get_weather_data(city_id):
    url = f"https://www.weather.com.cn/weather/{city_id}.shtml"

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
        "(KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
    }
    response = requests.get(url, headers=headers)
    response.encoding = 'utf-8'  # 防止乱码
    text = response.text

    info = []
    soup = BeautifulSoup(text, 'lxml')
    tags = soup.select("ul[class='t clearfix'] li")

    for tag in tags:
        day = tag.find("h1").get_text().strip()
        weather = tag.find("p", class_="wea").get_text().strip()
        tem = tag.find("p", class_="tem").get_text().strip()
        info.append((day, weather, tem))

    return info

作业②

要求:用requests和json解析方法定向爬取股票(东方财富网:https://www.eastmoney.com/)相关信息,并存储在数据库中

简介:
东方财富网站传输数据在接口' https://push2.eastmoney.com/api/qt/clist/get?np=1&fltt=1&invt=2&cb=jQuery3710324951759523461_1761760021174&fs=板块参数&fields=板块参数&fid=f3&pn=翻页数&pz=每页数量&po=1&dect=1&ut=fa5fd1943c7b386f172d6893dbfba10b&wbp2u=|0|0|0|web&_=时间戳 ',加载数据使用jsonp文件,简短裁剪可以化作json文件解析。

心得:
通过带时间戳的动态回调函数包装JSON数据,只需识别并去除jQuery回调函数(前缀和)后缀,即可将JSONP转换为标准JSON格式进行解析。这让我认识到很多网站采用JSONP实现跨域数据交互,核心在于理解其回调机制并做相应清洗处理,相比解析HTML页面能更高效地获取结构化数据。
中间发生过爬取太多断开remote,通过修改header中代理头解决,同时也告诫爬虫编写过程中,合适的爬取数量和本地加载是很有必要的

# jsonp转json
def parse_jsonp_simple(jsonp_str):
    start = jsonp_str.find('(')
    end = jsonp_str.rfind(')')
    if start != -1 and end != -1:
        json_str = jsonp_str[start+1:end]
        return json.loads(json_str)
    else:
        raise ValueError("无效的JSONP格式")
# 解析后写入
with open("eastmoney.csv", 'w', encoding='utf-8') as f:
    f.write("序号,股票代码,股票名称,最新价,涨跌幅(%),涨跌额,成交量(万手),成交额(亿元),振幅(%),最高价,最低价,今开,昨收\n")

for i in range(1,100):
    url = get_url(i)
    data = get_data(url)
    news_list = data['data']['diff']
    with open("eastmoney.csv", 'a', encoding='utf-8') as f:
        for j,stock in enumerate(news_list, 1):
            f.write(
                f"{(i-1)*20+j},"
                f"{stock.get('f12', '')}," # 股票代码
                f"{stock.get('f14', '')},"# 股票名称
                f"{stock.get('f2', 0)/100:.2f}," # 最新价
                f"{stock.get('f3', 0)/100:.2f},"  # 涨跌幅(%)
                f"{stock.get('f4', 0)/100:.2f}," # 涨跌额
                f"{stock.get('f5', 0)/10000:.2f},"  # 成交量转万手
                f"{stock.get('f6', 0)/100000000:.2f},"  # 成交额转亿元
                f"{stock.get('f7', 0)/100:.2f}," # 振幅(%)
                f"{stock.get('f15', 0)/100:.2f}," # 最高价
                f"{stock.get('f16', 0)/100:.2f}," # 最低价
                f"{stock.get('f17', 0)/100:.2f}," # 今开
                f"{stock.get('f18', 0)/100:.2f}\n") # 昨收

image
image

作业③:

要求:爬取中国大学2021主榜所有院校信息,并存储在数据库中,同时将浏览器F12调试分析的过程录制Gif加入至博客中。

简介:
所需数据在' https://www.shanghairanking.cn/_nuxt/static/1761118404/rankings/bcur/2021/payload.js '接口中,score数据很好找,但是province和Category数据用1-2字节字母替代。观察js代码发现function代码输入(开头)与结尾一一对应。

心得:
该网站将完整数据预渲染在payload.js文件中,虽然省份和院校类型字段采用1-2字节编码替代,但通过仔细分析JavaScript函数映射关系成功破解了编码规则。这让我认识到前端框架常采用静态化优化,关键数据往往隐藏在看似复杂的文件结构中,需要耐心分析JS代码逻辑才能完整解码数据含义,相比动态接口反而提供了更稳定的数据源。

# 构建映射字典,其中a,b从javascript脚本中复制
def get_dict(): 
  dict = {}
  a=("a, b, c, d, e, f, g......}
  b=('"", false, null, 0, "理工", "综合".....)
  a1 = a.split(', ')
    b1 = b.split(', ')
    for i in range(len(a1)):
        a1[i] = a1[i].strip().strip('"').strip("'")
        b1[i] = b1[i].strip().strip('"').strip("'")
        dict[a1[i]] = b1[i]
    return dict

rank

posted @ 2025-10-30 02:10  lisu6  阅读(32)  评论(0)    收藏  举报