数据采集与融合第二次作业

news/2024/10/19 2:25:23/文章来源:https://www.cnblogs.com/--xxxx-----/p/18468806
码云仓库地址 https://gitee.com/sun-jiahui22/crawl_project
作业1仓库地址 https://gitee.com/sun-jiahui22/crawl_project/tree/master/作业2/实验2.1
作业2的仓库地址 https://gitee.com/sun-jiahui22/crawl_project/tree/master/作业2/实验2.2
作业3的仓库地址 https://gitee.com/sun-jiahui22/crawl_project/tree/master/作业2/实验2.3
学号姓名 102202115孙佳会

作业①

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

序号 地区 日期 天气信息 温度
1 北京 7日(今天) 晴间多云 17℃/12℃
2 北京 8日(今天) 小雨 18℃/12℃

爬取7日天气预报

🌱实现思路

  • 一个数据库操作类 (WeatherDB):负责管理SQLite数据库,用于存储天气数据。
  • 一个天气预报类 (WeatherForecast):负责从天气网站获取特定城市的天气预报信息,通过forecastCity()方法抓取指定城市的天气预报,并解析页面中的天气信息。(主要)

🎨主要代码

# 该类处理从天气网站获取天气数据的功能
class WeatherForecast:def __init__(self):# 设置HTTP请求头,模拟浏览器访问self.headers = {"User-Agent": "Mozilla/5.0(Windows;U;Windows NT 6.0 x64;en-US;rv:1.9pre)Gecko/2008072421 Minefield/3.0.2pre"}# 预定义城市与其对应的天气预报代码self.cityCode = {"北京": "101010100", "上海": "101020100", "广州": "101280101", "深圳": "101280601"}# 获取某个城市的天气预报def forecastCity(self, city):if city not in self.cityCode.keys():print(city + " 的代码未找到")  # 如果城市不在预定义列表中,打印错误信息return# 构建天气预报的URLurl = "https://www.weather.com.cn/weather/" + self.cityCode[city] + ".shtml"try:# 发送HTTP请求获取网页数据req = urllib.request.Request(url, headers=self.headers)data = urllib.request.urlopen(req)data = data.read()# 使用UnicodeDammit处理编码问题dammit = UnicodeDammit(data, ["utf-8", "gbk"])data = dammit.unicode_markup# 使用BeautifulSoup解析HTML内容soup = BeautifulSoup(data, "lxml")# 选择包含天气信息的<li>标签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].texttemp = li.select("p[class='tem'] span")[0].text + '/' + li.select("p[class='tem'] i")[0].textprint(city, date, weather, temp)  # 打印获取到的天气数据# 将数据插入到数据库self.db.insert(city, date, weather, temp)except Exception as err:print(err)  # 处理解析过程中可能出现的错误except Exception as err:print(err)  # 处理HTTP请求可能出现的错误# 处理多个城市的天气数据def process(self, cities):self.db = WeatherDB()  # 创建数据库操作对象self.db.openDB()  # 打开数据库连接# 遍历城市列表并获取各城市的天气预报for city in cities:self.forecastCity(city)self.db.show()  # 显示数据库中的天气数据self.db.closeDB()  # 关闭数据库连接

运行结果

心得体会

  • 使用BeautifulSoup解析HTML内容时,最大的挑战在于处理不同网页的编码和结构问题,通过UnicodeDammit,成功解决了不同编码带来的解析错误。
  • 将数据库操作和天气抓取逻辑分别封装到WeatherDB和WeatherForecast类中,提高了代码的可读性,让代码更具扩展性和可维护性。

作业②

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

输出信息

股票代码 股票名称 最新报价 涨跌幅 涨跌额 成交量 成交额 振幅 最高 最低 今开 昨收
301522 N上大 79.85 1060.61 72.97 595675 5031370784.78 582.56 102.00 61.92 61.92 6.88

爬取股票信息

🌱实现思路

  1. 在谷歌浏览器中找到正确的url
  • 点击network,

    (因为这个截图不是当天截的,所以信息有所变化)

  • 复制url

  1. 数据库初始化
  • 创建或连接到一个本地 SQLite 数据库 (stocks.db)。
  • 如果数据库中尚未存在 stock_data 表,创建该表以存储股票相关数据
  1. API 数据抓取
  • 使用 requests.get(url) 发送 HTTP 请求,获取东方财富股票 API 的响应数据。
  • 对返回的 JSON 数据进行解析,提取包含股票信息的部分。
  1. 数据处理与存储
  • 将爬取的 JSON 数据解析后,提取出股票的相关信息,如代码、名称、最新价格等。
  • 使用 sqlite3 插入 SQL 语句将提取的每一条股票数据插入到数据库中。

🎨主要代码

只展示如何获取我们需要的股票以及主函数代码,数据库连接和插入到数据库部分不予赘述。

# 获取股票数据
def get_stock_data(url):response = requests.get(url)# 如果返回状态是200,说明请求成功if response.status_code == 200:try:# 提取 JSON 数据,去掉回调函数包裹的部分json_start = response.text.find('(') + 1json_end = response.text.rfind(')')json_str = response.text[json_start:json_end]data_json = json.loads(json_str)  # 解析 JSON 数据return data_json['data']['diff']  # 返回股票数据部分except (ValueError, KeyError):print("JSON 数据解析失败。")return []else:print(f"请求失败,状态码: {response.status_code}")return []
# 主函数:爬取数据并存储到数据库
def main():# 数据库连接conn, cursor = create_database()# 获取用户输入的页码范围start_page = int(input("请输入开始页码: "))end_page = int(input("请输入结束页码: "))# 遍历用户指定的页码范围for page in range(start_page, end_page + 1):print(f"正在爬取第 {page} 页数据...")# 定义API URL,动态修改页码参数 `pn`url = f"https://1.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112402758990905568719_1728977574693&pn={page}&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"# 获取股票数据stocks = get_stock_data(url)# 遍历每个股票信息,并插入到数据库for stock in stocks:stock_data = (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'),  # 昨收)# 插入数据到数据库insert_data(cursor, stock_data)# 提交事务并关闭数据库连接conn.commit()conn.close()print("数据爬取并存储完成!")# 显示表中数据并带列名display_data_with_columns()

运行结果
(这里爬取了两页)


心得体会

  • 跟着助教学习了怎样有效获取所需要的url,通过preview查看很直观,提高效率;
  • 对抓包获取json文件并解析的过程更加熟悉

作业③

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

排名 学校 省市 类型 总分
1 清华大学 北京 综合 969.2

爬取中国大学2021排名主榜

🌱实现思路

  1. 通过F12获得所需url,下面是调试分析的过程,用gif形式呈现:

  2. 请求并获取数据

首先,通过 requests.get() 方法从指定的 URL 请求 JavaScript 文件,该文件包含了中国大学排名的相关信息。通过 response.text 获取返回的文件内容,并将其存储为字符串 js_content

  1. 使用正则表达式提取数据

通过正则表达式 re.findall(),提取 JavaScript 文件中定义的所有学校数据对象,这些对象存储在 dU[...] 形式的数组中。提取的每个对象包含学校的名称、排名、省市、类型、总分等信息。

正则表达式的具体作用是匹配所有以 dU[数字] = {...} 形式出现的对象数据,其中 ... 表示学校的详细数据。

  1. 解析并提取关键信息

对每个提取到的 dU[...] 数据进行进一步解析:

  • 学校名称:通过 univNameCn 字段提取学校的中文名称。
  • 省市:通过 province 字段提取省市的符号,然后通过 province_mapping 将符号映射为实际的省市名称。
  • 类型:通过 univCategory 字段提取学校类型的符号,再通过 category_mapping 将符号映射为实际的类型名称。
  • 总分:通过 score 字段提取学校的总分。
  1. 将数据存储到 SQLite 数据库

利用 sqlite3 库将所有解析到的大学排名信息存储到本地的 SQLite 数据库中,表名为 rankings_2021

我们使用 pandas 将提取的数据列表转换为 DataFrame,然后使用 to_sql() 方法将 DataFrame 写入数据库。如果数据库中已经存在同名表,则通过 if_exists='replace' 替换该表。

🎨主要代码

# 请求数据
url = 'https://www.shanghairanking.cn/_nuxt/static/1728726515/rankings/bcur/202111/payload.js'
response = requests.get(url)
js_content = response.text# 正则表达式提取所有 dU 数组中的学校数据
matches = re.findall(r'dU\[\d+\]\s*=\s*\{(.*?)\};', js_content, re.DOTALL)universities = []
rank = 1  # 从1开始生成排名for match in matches:# 提取学校名称univ_name_cn = re.search(r'univNameCn:"(.*?)"', match)# 提取省份province_key = re.search(r'province:\s*(\w+)', match)# 提取学校类型category_key = re.search(r'univCategory:\s*(\w+)', match)# 提取总分score = re.search(r'score:\s*([\d\.]+)', match)if univ_name_cn and province_key and category_key and score:# 将省市和类型的符号转换为中文province = province_mapping.get(province_key.group(1), "未知省市")category = category_mapping.get(category_key.group(1), "未知类型")university = {'排名': rank,  # 按顺序生成排名'学校': univ_name_cn.group(1),'省市': province,'类型': category,'总分': score.group(1)}universities.append(university)rank += 1  # 增加排名# 将数据保存到 SQLite 数据库
# 创建SQLite数据库
conn = sqlite3.connect('university_rankings.db')
df = pd.DataFrame(universities)
df.to_sql('rankings_2021', conn, if_exists='replace', index=False)
conn.close()

由于存在地区及学校类型的映射,所以需要在代码中添加这部分:

# 创建省市和类型映射表
province_mapping = {"q": "北京", "u": "浙江", "B": "上海", "v": "湖北", "s": "陕西","k": "江苏", "A": "黑龙江", "y": "安徽", "t": "四川", "w": "广东","E": "山西", "r": "河北", "D": "天津", "J": "内蒙古", "p": "辽宁","z": "山东", "o": "河南", "x": "湖南", "C": "吉林", "H": "江西","L": "福建", "G": "重庆", "F": "贵州", "I": "云南", "ac": "广西","P": "西藏", "al": "青海", "aj": "宁夏", "ah": "新疆", "am": "海南","af": "甘肃"
}category_mapping = {"f": "综合", "e": "理工", "h": "师范", "m": "农业", "S": "医药"# 可以根据需要添加更多的类型映射
}

运行结果

心得体会

学习到了

  • 理解网络请求和数据抓取:通过使用 requests 库,能够模拟浏览器的 HTTP 请求,轻松抓取网页的静态数据。
  • 数据存储的简便性:使用 sqlite3pandas 相结合的方式,可以非常方便地将数据存储到 SQLite数据库中。通过将提取到的数据转换为 DataFrame 格式,然后调用 to_sql() 方法,轻松地实现了将数据存储到本地数据库,便于后续的数据分析和查询。这也体现了 pandas 库的高效和灵活。

遇到了什么问题
在抓取数据的过程中,遇到字段符号(省市和学校类型)难以识别的问题时,通过逐步调试和引入映射表的方法,最终成功解决了问题。

对数据抓取的思考
本次项目让我更加意识到网页数据的结构差异以及动态内容和静态内容的不同抓取方式。对于静态网页,直接抓取 JavaScript 文件中的数据是一种很有效的方式,但对于一些需要通过 API 动态加载的数据,我们可能需要借助更复杂的抓取技术。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IntelliJ IDEA 2024 安装使用 (附加激活码、补丁,亲测有效!)

第一步:下载 IDEA 安装包 访问 IDEA 官网,下载 IDEA 2024.1.4 版本的安装包,下载链接如下 : idea官方链接也可以在这里点击下载idea下载idea 第二步: 安装 IDEA点击xx 关掉程序! 第三步: 下载补丁 下载地址(里面包含激活码)https://pan.quark.cn/s/9dbfe698c064 补丁下载成…

PYNQ z2 使用xadcps读取xadc内部电压温度

使用xadcps只能和JTAG一样读取温度值和电压值,属于内部通道,读取不了外部通道的数据 添加zynq700核后进行配置 1.在PS-PL Configuration中, 取消勾选general里面的FCLK_RSTEN_N以及M_AXI_GP0_Interface2.在Peripheral IO Pins中勾选14 15对应的UART0, 同时对板卡电压进行配置,B…

控制结构

任何复杂的结构化程序都是由三种基本结构组成:顺序结构,分支结构、循环结构。 分支结构 单分支。if 双分支。if else 多分支。else if else if多分支 switch多分支 else if 于 switch多分支的区别循环结构 for循环 while循环 do while循环 for、while与do ... while语句的比较…

JAVA基础知识补漏

变量类型 1.类变量:static 2.实例变量:需要new 3.局部变量:必须初始化 常量 final 一般用大写表示 命名规范 所有变量、方法、类名:见名知意 类成员变量:首字母小写和驼峰原则:monthSalary 局部变量:首字母小写和驼峰原则 常量:大写字母和下划线:MAX_VALUE 类名:首字母大写和…

《恋与深空》游戏拆解

游戏背景与世界观《恋与深空》是一款女性向3D手游,设定在未来的科幻世界。玩家与多名男性角色互动,通过一系列科幻冒险推动剧情发展。角色设定与互动机制玩家可以与多个男性角色展开深度互动,每个角色不仅有鲜明的个性和背景故事,还伴随着成长线的发展。角色的互动不仅仅是…

CSP2024 前集训:多校A层冲刺NOIP2024模拟赛08

前言光顾着想 T2 了,但是不知道哪儿假了,只有 \(\dfrac{n}{k}\le 5\) 的点是对的,然后居然只有二十分,发现数据放错了,找喵喵改了成五十了。 然后 T1 因为重边挂没了。 T3 没调出来,确切的说是省的时间不多了打不完,就写了个部分分。 T4 咕了。 机房凳子没靠椅,一直坐着…

信息学奥赛复赛复习18-CSP-J2022-01解密-二分答案、二分找边界、二分时间复杂度、二分求最小

PDF文档公众号回复关键字:202410171 P8814 [CSP-J 2022] 解密 [题目描述] 给定一个正整数 k,有 k 次询问,每次给定三个正整数 ni,ei,di,求两个正整数 pi,qi,使 ni=piqi、eidi=(pi−1)(qi−1)+1 [输入格式] 第一行一个正整数 k,表示有 k 次询问。 接下来 k 行,第 i 行三个…

ollydbg逆向基础

实验目的 理解编译过程和调试信息,了解debug模式和release模式的exe进行逆向分析的过程。尝试多种方法找到main函数。实验环境系统:Windows 11软件:VS、ollydbg实验代码#include <stdio.h>int main() { printf("hello maqun"); return 0;}实验过程查找代…

PyCharm配置PyTorch环境(完美解决找不到Conda可执行文件python.exe问题)

出现的问题 以下是第一次踩坑的流程,具体解决方法附在后面 新建一个python项目,如图所示设置相关信息设置项目名称和位置 interpreter type(python解释器类型)==>自定义环境 环境==>Generate new,创建一个新环境 类型==>conda python==>3.11,如下所示,在创建好…

07-SQL注入(联合注入、报错注入、盲注)

1、在不依赖于DVWA后端数据库的情况,如何通过前端验证的方法判断DVWA中的注入点是数字型注入还是字符型注入?(提示:用假设法进行逻辑判断)在dvwa靶场中SQL Injection模块输入1 and 1=1如果是数字型注入输入内容没有被网站进行任何处理,可以查询到 输入内容被网站进行处理…

BUUCTF之Sandbox-bad

BUUCTF之Sandbox-bad 首先针对sandbox,我们需要有一个大概的认知,他是在一个代码执行环境下,脱离种种过滤和限制,最终成功拿到shell权限的过程,通常我们采用orw的方式来获取flag.orw全称only read write,只使用read write函数将flag读取并且打印,shellcode分为三个步骤使用…

trufflehog敏感信息搜集 核心框架代码分析

前言:trufflehog敏感信息搜集 核心框架代码分析 调度图代码思考 目前有一个需求,想要实现golang代码实现生产者消费者的模型