数据采集与融合技术实践--作业二

news/2024/10/20 16:45:54

数据采集与融合技术作业二

📌1.相关信息及链接

名称 信息及链接
学号姓名 102202108 王露洁
本次作业要求链接 https://edu.cnblogs.com/campus/fzu/2024DataCollectionandFusiontechnology/homework/13285
作业①所在码云链接 https://gitee.com/wanglujieeee/crawl_project/tree/master/作业2.1
作业②所在码云链接 https://gitee.com/wanglujieeee/crawl_project/tree/master/作业2.1
作业③所在码云链接 https://gitee.com/wanglujieeee/crawl_project/tree/master/作业2.3

📝2.作业内容

作业①:给定城市集7日天气预报的爬取

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

🗃️输出信息:Gitee文件夹链接

🌏解决思路

1.导入必要的库:

🔹BeautifulSoup:用于解析HTML和XML文档。

🔹UnicodeDammit:用于处理字符编码问题。

🔹urllib.request:用于从网页获取数据。

🔹sqlite3:用于与SQLite数据库进行交互。

2.定义城市和URL:

🔹使用一个字典cities来存储城市和它们对应的天气页面URL。

3.数据库连接和表格创建:

🔹连接到SQLite数据库(如果数据库不存在,则会自动创建)。

🔹创建一个名为weather的表,如果它还不存在的话。这个表包含序号、地区、日期、天气信息和温度等字段。

4.遍历每个城市并爬取天气信息:

🔹对于字典cities中的每个城市和URL:

🔹设置请求头以模拟浏览器访问。

🔹发送HTTP请求并读取响应数据。

🔹使用UnicodeDammit处理字符编码问题,确保数据以正确的编码格式读取。

🔹使用BeautifulSoup解析HTML内容。

🔹查找包含天气信息的HTML元素。

🔹遍历每个标签,提取日期、天气信息和温度。

🔹检查数据库中是否已存在相同地区和日期的记录,如果不存在,则将这些信息插入到数据库中。

🚀代码实现

from bs4 import BeautifulSoup
from bs4 import UnicodeDammit
import urllib.request
import sqlite3# 城市和其对应的天气页面URL
cities = {"北京": "https://www.weather.com.cn/weather/101010100.shtml","上海": "https://www.weather.com.cn/weather/101020100.shtml","广州": "https://www.weather.com.cn/weather/101280101.shtml","杭州": "https://www.weather.com.cn/weather/101210101.shtml"
}# 数据库连接和表格创建
conn = sqlite3.connect('cities_weather.db')
cursor = conn.cursor()
cursor.execute('''  CREATE TABLE IF NOT EXISTS weather (  序号 INTEGER PRIMARY KEY AUTOINCREMENT,  -- 让数据库自动生成唯一序号地区 varchar(16),日期 varchar(16),  天气信息 varchar(64),  温度 varchar(32))  
''')# 遍历每个城市及其URL,爬取天气信息
for city, url in cities.items():try:headers = {"User-Agent": "Mozilla/5.0(Windows;U;Windows NT 6.0 x64;en-US;rv:1.9pre)Gecko/2008072421 Minefield/3.0.2pre"}req = urllib.request.Request(url, headers=headers)data = urllib.request.urlopen(req).read()dammit = UnicodeDammit(data, ["utf-8", "gbk"])data = dammit.unicode_markup# 使用 BeautifulSoup 解析网页内容soup = BeautifulSoup(data, "lxml")lis = soup.select("ul[class='t clearfix'] li")# 遍历每一天天气数据for li in lis:try:date = li.select("h1")[0].textweather = li.select("p[class='wea']")[0].texttem = li.select("p[class='tem']")[0].text.strip()  # 获取温度,去除空白# 检查数据库中是否已存在该地区和日期的记录cursor.execute('SELECT COUNT(*) FROM weather WHERE 地区 = ? AND 日期 = ?', (city, date))exists = cursor.fetchone()[0]if exists == 0:# 插入数据到数据库cursor.execute('''  INSERT INTO weather (地区, 日期, 天气信息, 温度) VALUES (?, ?, ?, ?)  ''', (city, date, weather, tem))except Exception as e:print(f"处理 {city} 的天气信息时出错: {e}")# 提交城市的数据conn.commit()except Exception as e:print(f"爬取 {city} 的天气信息时出错: {e}")# 查询并打印数据库中的所有城市数据以验证插入是否成功
cursor.execute('SELECT * FROM weather')
rows = cursor.fetchall()# 打印表头
print("序号 | 地区 | 日期    | 天气信息  | 温度")
print("-" * 50)  # 打印分隔线
for row in rows:print(f"{row[0]:<5} | {row[1]:<5} | {row[2]:<10} | {row[3]:<10} | {row[4]:<10}")# 关闭数据库连接
conn.close()

🌞运行结果截图


🌈心得体会

这个作业之前有做过,但是该天气网站似乎跟之前不太一样,当天的温度值显示出实时气温,而没有显示最高温和最低温,所以用之前的代码只能爬出6天的天气状况即不包括当天的天气。我改了很久,就连我自己都不知道自己怎么爬出来像现在这样的数据。(就在此时)刚刚又运行了改过的代码,发现相同的代码它又能把当天的最高位和最低温爬出来了。真的是大大的疑惑,,,一会而我会再看看怎么个事。现在我意识到了网页是在不断变化之中的,所以我们的爬虫代码也应该跟随它的变化而变化,从而才能保证数据的准确性和有效性。

作业②:爬取股票相关信息

✒️要求:用requests和自选提取信息方法定向爬取股票相关信息,并存储在数据库中。 候选网站:东方财富网:https://www.eastmoney.com/新浪股票:http://finance.sina.com.cn/stock/ 技巧:在谷歌浏览器中进入F12调试模式进行抓包,查找股票列表加载使用的url,并分析api返回的值,并根据所要求的参数可适当更改api的请求参数。根据URL可观察请求的参数f1、 f2可获取不同的数值,根据情况可删减请求的参数。

🗃️输出信息:Gitee文件夹链接

🌏解决思路

1.初始化数据库并创建表格 (initialize_db 函数):

🔹连接到SQLite数据库(如果数据库不存在则创建)。

🔹创建一个名为 stock_info 的表格,用于存储股票的各种信息,如股票代码、名称、价格等。

2.插入股票数据 (save_data 函数):

🔹接收一个包含股票信息的元组,并将其插入到 stock_info 表格中。

3.获取股票市场信息 (fetch_market_data 函数):

🔹发起HTTP GET请求到指定的API URL。

🔹解析返回的JSON数据,提取所需的股票信息。

🔹返回解析后的股票数据列表。

4.显示带有列名的数据并导出到Excel (show_stock_data 函数):

🔹从数据库中读取所有股票数据。

🔹使用 pandas 显示数据。

🔹将数据导出到Excel文件。

5.主逻辑 (main_program 函数):

🔹初始化数据库连接和游标。

🔹获取用户输入的页码范围。

🔹循环遍历指定页码范围,生成API URL,并获取股票数据。

🔹遍历股票数据列表,提取每只股票的信息,并保存到数据库中。

🔹提交事务并关闭数据库连接。

🔹显示存储的数据并导出到Excel。

🚀代码实现

import requests
import sqlite3
import json
import pandas as pd# 初始化数据库并创建表格
def initialize_db():connection = sqlite3.connect('market_data.db')  # 创建或连接数据库db_cursor = connection.cursor()# 创建存储股票数据的表格db_cursor.execute('''CREATE TABLE IF NOT EXISTS stock_info (symbol TEXT, name TEXT, latest_price REAL, price_change_rate REAL, price_change_amount REAL, trade_volume INTEGER, trade_value REAL, amplitude REAL, high_price REAL, low_price REAL, opening_price REAL, closing_price REAL)''')connection.commit()return connection, db_cursor# 插入股票数据
def save_data(db_cursor, stock_info):db_cursor.execute('''INSERT INTO stock_info (symbol, name, latest_price, price_change_rate, price_change_amount, trade_volume, trade_value, amplitude, high_price, low_price, opening_price, closing_price)VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', stock_info)# 获取股票市场信息
def fetch_market_data(api_url):try:result = requests.get(api_url)if result.status_code == 200:data_start = result.text.find('(') + 1data_end = result.text.rfind(')')json_data = result.text[data_start:data_end]parsed_data = json.loads(json_data)return parsed_data['data']['diff']else:print(f"获取数据失败,状态码: {result.status_code}")return []except Exception as error:print(f"请求出错: {error}")return []# 显示带有列名的数据并导出到Excel
def show_stock_data():connection = sqlite3.connect('market_data.db')query = "SELECT * FROM stock_info"# 使用 pandas 读取数据库中的数据dataframe = pd.read_sql_query(query, connection)# 显示数据print(dataframe)# 将数据导出到 Excelexcel_filename = 'stock_data.xlsx'dataframe.to_excel(excel_filename, index=False)print(f"数据已囚禁到 {excel_filename} 文件中。")connection.close()# 主逻辑:抓取并存储股票数据
def main_program():# 初始化数据库connection, db_cursor = initialize_db()# 获取用户输入的页码范围start_pg = int(input("你想从哪页开始: "))end_pg = int(input("到哪页结束: "))# 循环抓取指定页码的数据for page_num in range(start_pg, end_pg + 1):print(f"快了!已经到第 {page_num} 页了!")# 动态生成URLapi_url = f"https://1.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112402758990905568719_1728977574693&pn={page_num}&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&dect=1&wbp2u=|0|0|0|web&fid=f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152&_=1728977574694"# 获取股票数据stock_list = fetch_market_data(api_url)# 遍历并存储每只股票的数据for stock in stock_list:stock_entry = (stock.get('f12'),  # 股票代码stock.get('f14'),  # 股票名称stock.get('f2'),  # 最新报价stock.get('f3'),  # 涨跌幅stock.get('f4'),  # 涨跌额stock.get('f5'),  # 成交量stock.get('f6'),  # 成交额stock.get('f7'),  # 振幅stock.get('f15'),  # 最高价stock.get('f16'),  # 最低价stock.get('f17'),  # 今开价stock.get('f18'),  # 昨收价)# 保存到数据库save_data(db_cursor, stock_entry)# 提交事务并关闭数据库connection.commit()connection.close()print("数据已成功逮捕并关押在数据库!")# 显示存储的数据并导出到 Excelshow_stock_data()# 运行程序
if __name__ == "__main__":main_program()

🌞运行结果截图

🌈心得体会

这是我第一次使用F12调试模式进行抓包,之后再查找股票列表加载使用的url,并分析api返回的值,这是一个不太容易的过程,但是我却从中学到很多。查看过我们所需要抓的包的内容并进行分析之后,才知道首先从请求返回的响应中提取出json格式的数据,再用属性来获取对应的值。其中回调函数的参数即是一个json对象,而回调函数的作用是实现异步代码的执行,这些零散的知识点都是我后来查的(虽然查的越多越困惑)。通过属性获取的值是一个列表,所以我们还需要用循环来遍历每个元素,在每个元素中再进行筛选,为的是输出我们所需要的数据。总之我认为难点就是对api返回数据的分析以及如何利用适合的方式(正则表达式,键值对,函数等)检索到我们所需要的数据。

作业③:爬取大学排名相关信息

✒️要求:爬取中国大学2021主榜(https://www.shanghairanking.cn/rankings/bcur/2021)所有院校信息,并存储在数据库中,同时将浏览器F12调试分析的过程录制Gif加入至博客中。技巧:分析该网站的发包情况,分析获取数据的api

🗃️输出信息:Gitee文件夹链接

Gif:

🌏解决思路

1.数据抓取

🔹使用 requests 模块从提供的API URL中抓取数据。

🔹通过正则表达式提取API返回的JavaScript中的大学名称和分数。

🔹univNameCn 是大学名称,score 是分数。

🔹re.compile(r'univNameCn:\s"([^"]+)",\s.?score:\s([\d.]+)', re.DOTALL) 匹配大学名称和分数。

2.数据保存

🔹通过 INSERT INTO 语句将提取的大学名称和分数插入SQLite数据库中。

🔹如果遇到数据库插入冲突(如相同大学名称的记录已经存在),使用 try-except 块来忽略重复记录。

3.数据显示和导出

🔹使用 pandas 读取数据库中的所有大学数据,并打印在控制台中。

🔹同时将数据导出为Excel文件(university_data.xlsx)。

🚀代码实现

import requests
import sqlite3
import json
import pandas as pd
import re# 初始化数据库并创建表格
def initialize_db():connection = sqlite3.connect('university_data.db')db_cursor = connection.cursor()db_cursor.execute('''  CREATE TABLE IF NOT EXISTS university_info (  id INTEGER PRIMARY KEY AUTOINCREMENT,  学校 TEXT NOT NULL,  分数 REAL NOT NULL  )  ''')connection.commit()return connection, db_cursor# 保存数据到数据库
def save_data(db_cursor, university_info):try:db_cursor.execute('''  INSERT INTO university_info (学校, 分数)  VALUES (?, ?)  ''', university_info)except sqlite3.IntegrityError:# 如果记录已存在(基于学校名称的唯一性),则忽略插入pass# 从API获取大学数据def fetch_university_data(api_url):try:result = requests.get(api_url)result.raise_for_status()  # 如果状态码不是200,将引发HTTPError异常# 假设数据被包裹在某种JavaScript对象中,我们需要提取出JSON部分# 注意:这里的字符串操作是基于假设的API响应格式,实际使用时可能需要调整data_start = result.text.find('return {') + len('return {')data_end = result.text.find('};', data_start)  # 假设数据以'};'结尾data = result.text[data_start:data_end]# 使用正则表达式匹配所有大学数据pattern = re.compile(r'univNameCn:\s*"([^"]+)",\s*.*?score:\s*([\d\.]+)', re.DOTALL)matches = pattern.findall(data)# 将匹配结果转换为结构化数据universities = [{'university_name': match[0], 'score': float(match[1])} for match in matches]return universitiesexcept Exception as error:print(f"请求出错: {error}")return []# 显示并导出数据到Exceldef show_university_data(connection):query = "SELECT * FROM university_info"dataframe = pd.read_sql_query(query, connection)print(dataframe)dataframe.to_excel('university_data.xlsx', index=False)print("数据已导出到 university_data.xlsx 文件中。")# 主逻辑:抓取并存储大学数据
def main_program():connection, db_cursor = initialize_db()api_url = "https://www.shanghairanking.cn/_nuxt/static/1728872418/rankings/bcur/2021/payload.js"university_list = fetch_university_data(api_url)for university in university_list:save_data(db_cursor, (university['university_name'], university['score']))connection.commit()connection.close()print("数据已成功存储在数据库中!")# 重新打开数据库连接以显示和导出数据(或者可以在save_data后保持连接打开)with sqlite3.connect('university_data.db') as connection:show_university_data(connection)# 运行程序if __name__ == "__main__":main_program()

🌞运行结果截图

🌈心得体会

我做这道题的过程可以说是非常非常非常非常非常非常非常非常的艰难。虽然之前有爬取过大学的排行榜,但是方法不同对我来说就相差很多。而且我对抓包的方法很不熟悉,上次做抓包还是前面的第二题,所以我受第二题的影响很大,以为把第二题的代码稍微改改就能在这题上运行出来,于是我改了很久很久很久,出现了各种各样的错误,gpt都快被我问冒烟了还是没能改出来。后来我意识到这两个包的内容并不相同,所以提取数据的方式不会一样,要分别进行分析。我本来还想用键值对的方式做这道题,所以想把响应内容中的json格式的内容提取出来,光是提取就花费了很大的功夫,结果当我想把这些内容利用函数json.loads()转换成python对象(字典之类的)时,一直报错,我不知道是为什么就一直改改改一直尝试,不知过了多久我才知道我从响应体中提取到的文本内容根本就不是json格式,他只是长得像而已,因为它的键并没有被双引号所包裹,所以这个办法是行不通的(真的心疼我的时间和精力)。然后我就开始用正则表达式来直接提取所需字段,这也花了很长时间,但是最后是能做出来的,庆幸庆幸。我做出来之后还翻看了其他同学的报告,发现他们有人json.load()成功了,我没有搞明白,难道是我提取响应体的内容不对吗,等我写完了这篇报告,再去细看。总之这次作业真的把我难到了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/73863.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

欧拉路径学习笔记

简介 定义:欧拉回路:通过图中每条边恰好一次的回路 欧拉通路:通过图中每条边恰好一次的通路 欧拉图:具有欧拉回路的图 半欧拉图:具有欧拉通路但不具有欧拉回路的图摘自: oi-wiki。 定义说白了就是小学的一笔画问题,这里直接给出三道例题。P7771 【模板】欧拉路径,CF508D…

网站连接数据库怎么办

连接网站到数据库通常涉及以下几个步骤:选择数据库类型:常见的数据库类型有 MySQL、PostgreSQL、SQLite、MongoDB 等。 根据项目需求选择合适的数据库。安装数据库驱动:根据所选的数据库类型和开发环境,安装相应的数据库驱动。 例如,对于 Python 和 MySQL,可以使用 mysql…

td导航zlibrary镜像入口及国内可访问地址

TD导航是一个综合性的网址导航网站,它致力于为用户提供便捷、高效的上网体验。在这个平台上,用户可以轻松找到各类热门网站和实用工具,无论是新闻资讯、社交娱乐、购物消费,还是学习教育、工作办公等领域,TD导航都提供了丰富的资源链接。 TD导航的界面设计简洁明了,分类清…

20222422 2024-2025-1 《网络与系统攻防技术》实验二实验报告

一.实验内容 (1)使用netcat获取主机操作Shell,cron启动某项任务(任务自定) PS:cron是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程 (2)使用socat获取主机操作Shell, 任务计划启动 (3)使用MSF meterpreter(或其他软件)生成可执行文件,利用ncat或soc…

2024-2025-1(20241321)《计算机基础与程序设计》第四周学习总结

这个作业属于哪个课程 <班级的链接>(2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(2024-2025-1计算机基础与程序设计第一周作业)这个作业的目标 <了解并学习AI功能,回顾一周课程心得>作业正文 ... 本博客链接https://www.cnblo…

『模拟赛』多校A层冲刺NOIP2024模拟赛09(更新 T4)

『模拟赛记录』多校A层冲刺NOIP2024模拟赛09Rank 还行A. 排列最小生成树 (pmst) 签,有点可惜。 考虑连 \(i\) 与 \(i+1\) 时,所有边边权都是小于 \(n\) 的,因此我们只考虑边权小于 \(n\) 的边即可。因为边权为 \(|p_i-p_j|\times|i-j|\),所以只考虑 \(|p_i-p_j|\lt \sqrt{n…

云原生架构视图

关于云原生的概念,业内有没有统一的定义,比较主流的还是CNCF(Cloud Native Computing Foundation,云原生计算基金会)对云原生的定义。原文如下: Cloud native technologies empower organizations to build and run scalable applications in public, private, and hybrid …