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

学号姓名 102202132 郑冰智
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/2024DataCollectionandFusiontechnology/homework/13285
这个作业的目标 爬取天气网、股票相关信息、中国大学2021主榜所有院校信息,并存储在数据库中
实验二仓库地址 https://gitee.com/zheng-bingzhi/2022-level-data-collection/tree/master/实验二

一、作业①:中国气象网天气预报爬取与存储

要求:在中国气象网(http://www.weather.com.cn)给定城市集的7日天气预报,并保存在数据库。
输出信息:
Gitee文件夹链接:https://gitee.com/zheng-bingzhi/2022-level-data-collection/blob/master/实验二/weather collection.py

1.1.核心代码

1.1.1. WeatherDB类

  • 该类用于与SQLite数据库交互。关键代码如下:
self.con = sqlite3.connect("weathers.db")
self.cursor.execute(
    "create table weathers (wCity varchar(16), wDate varchar(16), "
    "wweather varchar(64), wTemp varchar(32),constraint pk_weather primary key (wCity,wDate))"
)

1.1.2. WeatherForecast类

  • 其forecastCity(city)方法用于获取指定城市天气数据。核心代码如下:
req = urllib.request.Request(url, headers=self.headers)
data = urllib.request.urlopen(req).read()
soup = BeautifulSoup(data, "lxml")
lis = soup.select("ul[class='t clearfix'] li")
for li in lis:
    date = li.select("h1")[0].text
    weather = li.select("p[class='wea']")[0].text
    temp = li.select("p[class='tem'] span")[0].text + "/" + li.select("p[class='tem'] i")[0].text
    self.db.insert(city, date, weather, temp)

1.2.实现结果

成功获取并存储了指定城市的7日天气预报数据,如以下截图所示:

1.3实验心得

  • 1.3.1. 数据库管理功能定义
    创建WeatherDB类实现数据库操作,包括openDB()打开数据库并创建表格,insert()插入数据,closeDB()提交并关闭连接。
  • 1.3.2. 天气数据爬取与处理实现
    WeatherForecast类的forecastCity()方法利用urllib和BeautifulSoup获取并解析天气数据,再通过WeatherDB插入数据库。

二、作业②:东方财富网股票信息爬取与存储

要求:用requests和BeautifulSoup库方法定向爬取股票相关信息,并存储在数据库中。
候选网站:东方财富网:https://www.eastmoney.com/
新浪股票:http://finance.sina.com.cn/stock/
技巧:在谷歌浏览器中进入F12调试模式进行抓包,查找股票列表加载使用的url,并分析api返回的值,并根据所要求的参数可适当更改api的请求参数。根据URL可观察请求的参数f1、f2可获取不同的数值,根据情况可删减请求的参数。
参考链接:https://zhuanlan.zhihu.com/p/50099084
输出信息:
Gitee文件夹链接:https://gitee.com/zheng-bingzhi/2022-level-data-collection/blob/master/实验二/gupiao.py

2.1.核心代码

2.1.1. insert_data_to_db(stock_data)函数

  • 用于批量插入股票数据到SQLite数据库,代码如下:
def insert_data_to_db(stock_data):
    conn = sqlite3.connect('stock_data.db')
    cursor = conn.cursor()
    cursor.executemany('''
        INSERT INTO stocks (
            股票名称, 股票价格, 涨跌幅, 涨跌额, 成交量, 成交额, 换手率, 
            最高价, 最低价, 开盘价, 收盘价, 市净率, 市盈率_TTM
        ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
    ''', stock_data)
    conn.commit()
    conn.close()

2.1.2. fetch_page_data(page_number)函数

  • 抓取指定页码股票数据,解析JSON数据并提取所需字段,代码如下:
def fetch_page_data(page_number):
    url = f"https://31.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112408346152866958425_1728977618714&pn={page_number}&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&_={1728977618716}"
    response = requests.get(url)
    json_data = response.text
    json_data_cleaned = json_data[json_data.index("(")+1 : json_data.rindex(")")]
    data = json.loads(json_data_cleaned)
    selected_data = []
    for item in data['data']['diff']:
        selected_item = (
            item.get('f14'),          # 股票名称
            item.get('f2'),           # 股票价格
            item.get('f3'),           # 涨跌幅(%)
            item.get('f4'),           # 涨跌额
            item.get('f5'),           # 成交量(手)
            item.get('f6'),           # 成交额(万元)
            item.get('f7'),           # 换手率(%)
            item.get('f15'),          # 最高价
            item.get('f16'),          # 最低价
            item.get('f17'),          # 开盘价
            item.get('f18'),          # 收盘价
            item.get('f23'),          # 市净率
            item.get('f115')          # 市盈率(TTM)
        )
        selected_data.append(selected_item)
    return selected_data

2.1.3. scrape_all_pages_to_db(total_pages)函数

  • 循环抓取多页股票数据并存储到数据库,代码如下:
def scrape_all_pages_to_db(total_pages):
    all_data = []
    for page in range(1, total_pages + 1):
        page_data = fetch_page_data(page)
        all_data.extend(page_data)
    insert_data_to_db(all_data)
    print(f"数据已保存到数据库 (共 {len(all_data)} 条记录)")

2.2实验结果

成功爬取并存储股票数据,截图如下:

2.3实验心得

  • 2.3.1. 技术掌握与运用:
    熟悉了requests和BeautifulSoup在Web数据抓取中的应用,尤其是JSON数据解析处理能力得到提升,同时强化了数据库操作理解。
  • 2.3.2. 问题与解决
    爬取时遇到API数据嵌套冗余问题,通过字符串清洗和JSON解析解决数据类型转换、字段对齐等问题,批量执行插入优化数据库性能。
  • 2.3.3. 改进与优化
    数据抓取和存储效率有提升空间,可考虑多线程爬取和使用更高级数据存储方案(如MongoDB)。

三、作业③:中国大学2021主榜院校信息爬取与存储

要求:爬取中国大学2021主榜(https://www.shanghairanking.cn/rankings/bcur/2021)所有院校信息,并存储在数据库中,同时将浏览器F12调试分析的过程录制Gif加入至博客中。
技巧:分析该网站的发包情况,分析获取数据的api
输出信息:
Gitee文件夹链接:https://gitee.com/zheng-bingzhi/2022-level-data-collection/blob/master/实验二/university_rankings.py

3.1核心代码

3.1.1. 发送HTTP GET请求获取数据

  • 代码如下:
url = 'https://www.shanghairanking.cn/_nuxt/static/1728872418/rankings/bcur/2021/payload.js'
headers = {
    'cookie': '_clck=93jbcf%7C2%7Cfq1%7C1719; Hm_lvt_af1fda4748dacbd3ee2e3a69c3496570=1726414171,1728974129,1728998508; HMACCOUNT=0427200578AECD82; Hm_lpvt_af1fda4748dacbd3ee2e3a69c3496570=1729000764; _clsk=1du80lb%7C1729000766146%7C8%7C1%7Cz.clarity.ms%2Fcollect',
    'referer': 'https://www.shanghairanking.cn/rankings/bcur/2021',
    'user - agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0'
}
response = requests.get(url, headers=headers)

3.1.2. 解析数据并提取信息

  • 代码如下:
if response.status_code == 200:
    file_content = response.text
else:
    print(f"请求失败,状态码: {response.status_code}")
    exit()
extracted_data = []
if univ_data_match:
    univ_data_str = univ_data_match.group(1)
    university_pattern = re.compile(r'\{([^}]+)\}')
    universities = university_pattern.findall(univ_data_str)
    for university in universities:
        data_dict = {}
        for item in university.split(','):
            key_value = item.split(':')
            if len(key_value) == 2:
                key = key_value[0].strip().replace('"', '').replace("'", "")
                value = key_value[1].strip().replace('"', '').replace("'", "")
                if key == 'univNameCn':
                    data_dict[key] = value
                elif key in ['province', 'univCategory']:
                    data_dict[key] = mapping.get(value, value)
                elif key == 'score':
                    try:
                        data_dict[key] = float(value)
                    except ValueError:
                        data_dict[key] = None
        extracted_data.append(data_dict)

3.1.3. 将数据存入SQLite数据库

  • 代码如下:
conn = sqlite3.connect('university_rankings.db')
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS university (univNameCn TEXT, province TEXT, univCategory TEXT, score REAL)''')
cursor.executemany('''INSERT INTO university (univNameCn, province, univCategory, score) VALUES (:univNameCn, :province, :univCategory, :score)''', extracted_data)
conn.commit()

3.2.浏览器F12调试分析的过程

3.3.实验结果

成功爬取并存储大学排名数据,截图如下:

3.4.实验心得

  • 3.4.1. 发包情况分析
    排名数据通过API请求获取,URL为https://www.shanghairanking.cn/_nuxt/static/1728872418/rankings/bcur/2021/payload.js,是静态资源请求。请求headers包含cookie、referer和user - agent,避免反爬虫拦截。该网站采用单页应用(SPA),通过JavaScript动态渲染数据,便于抓取完整数据集。
  • 3.4.2. API数据结构分析
    返回数据是JavaScript对象,非传统JSON格式。数据一次性加载且URL固定,便于大规模爬取。主要字段有univNameCn、province、univCategory、score等,通过正则表达式提取,解析时需处理字段映射和数值异常,并存储到SQLite数据库。
posted @ 2024-10-18 21:47  郑冰智  阅读(21)  评论(0编辑  收藏  举报