作业2

一、作业内容

作业①:

要求:在中国气象网(http://www.weather.com.cn)给定城市集的7日天气预报,并保存在数据库。
输出信息:
Gitee文件夹链接:https://gitee.com/wanghew/homework/tree/master/作业2

from bs4 import BeautifulSoup  # 用于解析HTML和XML文档
from bs4.dammit import UnicodeDammit  # 用于处理编码问题
import urllib.request  # 用于发送网络请求
import sqlite3  # 用于与SQLite数据库交互
# 定义一个天气数据库类
class WeatherDB:
    def __init__(self):
        self.cursor = None  # 数据库游标
        self.con = None  # 数据库连接对象

    # 打开数据库连接,并尝试创建表
    def openDB(self):
        self.con = sqlite3.connect("weathers.db")  # 连接到 SQLite 数据库文件 weathers.db
        self.cursor = self.con.cursor()  # 创建游标对象
        try:
            # 尝试创建表 weathers,如果不存在的话
            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))")
        except Exception as err:
            print(err)  # 如果创建失败(比如表已存在),则打印错误信息
            self.cursor.execute("delete from weathers")  # 清空表中的数据

    # 关闭数据库连接
    def closeDB(self):
        self.con.commit()  # 提交事务
        self.con.close()  # 关闭连接

    # 向数据库中插入一条天气记录
    def insert(self, city, date, weather, temp):
        try:
            # 插入城市、日期、天气状况和温度到表中
            self.cursor.execute("insert into weathers (wCity, wDate, wWeather, wTemp) values (?, ?, ?, ?)", (city, date, weather, temp))
        except Exception as err:
            print(err)  # 如果插入失败,则打印错误信息

    # 显示所有天气记录
    def show(self):
        self.cursor.execute("select * from weathers")  # 查询表中的所有记录
        rows = self.cursor.fetchall()  # 获取查询结果
        print("%-16s%-16s%-32s%-16s" % ("city", "date", "weather", "temp"))  # 打印表头
        for row in rows:  # 遍历每条记录
            print("%-16s%-16s%-32s%-16s" % (row[0], row[1], row[2], row[3]))  # 打印每条记录

# 定义一个天气预报类
class WeatherForecast:
    def __init__(self):
        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 = {"郑州": "101180101", "银川": "101170101", "福州": "101230101", "北京": "101010100"}  # 城市代码字典

    # 根据城市名称获取并存储天气预报
    def forecastCity(self, city):
        if city not in self.cityCode.keys():  # 检查城市是否在城市代码字典中
            print(city + " 找不到代码")  # 如果不在,则打印错误信息
            return
        url = "http://www.weather.com.cn/weather/" + self.cityCode[city] + ".shtml"  # 构造请求URL
        try:
            req = urllib.request.Request(url, headers=self.headers)  # 创建请求对象
            data = urllib.request.urlopen(req)  # 发送请求
            data = data.read()  # 读取响应内容
            dammit = UnicodeDammit(data, ["utf-8", "gbk"])  # 使用UnicodeDammit来解决编码问题
            data = dammit.unicode_markup  # 解码后的文本
            soup = BeautifulSoup(data, "lxml")  # 使用BeautifulSoup解析HTML
            lis = soup.select("ul[class='t clearfix'] li")  # 选择天气列表项
            x = 0  # 计数器,用于区分今天和其他天
            for li in lis:  # 遍历每个列表项
                try:
                    date = li.select('h1')[0].text  # 提取日期
                    weather = li.select('p[class="wea"]')[0].text  # 提取天气状况
                    if x == 0:  # 如果是今天的天气
                        x += 1
                        temp = li.select('p[class="tem"] i')[0].text  # 提取温度
                    else:  # 如果不是今天的天气
                        temp = li.select('p[class="tem"] span')[0].text + "/" + li.select('p[class="tem"] i')[0].text  # 提取最高温和最低温
                    print(city, date, weather, temp)  # 打印天气信息
                    self.db.insert(city, date, weather, temp)  # 插入数据库
                except Exception as err:
                    print(err)  # 如果提取过程中出错,则打印错误信息
        except Exception as err:
            print(err)  # 如果请求过程中出错,则打印错误信息

    # 处理多个城市的天气预报
    def process(self, cities):
        self.db = WeatherDB()  # 创建WeatherDB实例
        self.db.openDB()  # 打开数据库连接
        for city in cities:  # 遍历城市列表
            self.forecastCity(city)  # 对每个城市调用forecastCity方法
        # self.db.show()  # 可选:显示数据库中的所有天气记录
        self.db.closeDB()  # 关闭数据库连接
# 创建WeatherForecast实例
ws = WeatherForecast()
# 调用process方法处理四个城市的天气预报
ws.process(["郑州", "银川", "福州", "北京"])
print("completed")  # 打印完成信息

效果:

心得体会

通过这次实践,我深刻体会到了Python在数据抓取与处理方面的强大能力。利用BeautifulSoup库解析网页结构、提取天气信息的过程让我对HTML文档的结构有了更清晰的认识。同时,使用SQLite数据库来存储数据,不仅学习了如何操作数据库,还理解了数据持久化的重要性。虽然过程中遇到了不少挑战,比如处理不同城市的数据格式差异等,但最终成功实现功能让我感到非常有成就感

作业②

要求:用requests和BeautifulSoup库方法定向爬取股票相关信息,并存储在数据库中。东方财富网:https://www.eastmoney.com/
码云地址:https://gitee.com/wanghew/homework/tree/master/作业2

import csv  # 导入处理CSV文件的库
import json  # 导入处理JSON数据的库
import requests  # 导入发送HTTP请求的库
from prettytable import PrettyTable  # 导入用于生成表格的库

def main():
    # 定义请求的URL和请求头
    url = 'https://22.push2.eastmoney.com/api/qt/clist/get?pn=1&pz=6000&po=1&fid=f3&fs=m:1+t:2&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'
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
    # 获取数据
    result = getData(url, headers)
    # 打印数据
    printData(result)
    # 保存数据到CSV文件
    saveData(result)

def getData(baseUrl, headers):
    # 发送GET请求获取数据
    response = requests.get(url=baseUrl, headers=headers)
    # 解析JSON响应数据
    data = json.loads(response.text)['data']['diff']
    result = []
    for key, value in data.items():
        # 提取并格式化需要的字段
        latest_price = '%.2f' % (value['f2'] / 100)  # 最新价
        change_rate = '%.2f' % (value['f3']) + '%'  # 涨跌幅
        change_amount = '%.2f' % (value['f4'] / 100)  # 涨跌额
        volume = '%.2f' % (value['f5'] / 10000) + '万'  # 成交量(手)
        amount = '%.2f' % (value['f6'] / 100000000) + '亿'  # 成交额
        # 将提取的数据添加到结果列表中
        result.append([
            key,
            value['f12'],
            value['f14'],
            latest_price,
            change_rate,
            change_amount,
            volume,
            amount
        ])
    return result  # 返回处理后的数据列表
def printData(result):
    # 创建一个PrettyTable对象
    table = PrettyTable()
    # 设置表头
    table.field_names = [
        "序号", "代码", "名称", "最新价", "涨跌幅", "涨跌额", "成交量(手)", "成交额"
    ]
    # 添加数据行
    table.add_rows(result)
    # 打印表格
    print(table)
def saveData(result):
    # 打开CSV文件,准备写入
    with open('上证A股股票数据.csv', 'w', encoding='utf-8', newline='') as file:
        writer = csv.writer(file)
        # 写入表头
        writer.writerow([
            "序号", "代码", "名称", "最新价", "涨跌幅", "涨跌额", "成交量(手)", "成交额"
        ])
        # 写入数据行
        writer.writerows(result)

if __name__ == "__main__":
    main()

效果:

心得体会:

整个过程让我更加深入理解了数据抓取与处理的实际应用,并且增强了我的编程实践能力。尽管遇到了一些挑战,比如对API返回的数据结构不够了解,但经过查阅文档和调试后最终顺利完成了任务

作业③:

要求:爬取中国大学2021主榜(https://www.shanghairanking.cn/rankings/bcur/2021) 所有院校信息,并存储在数据库中
码云地址:https://gitee.com/wanghew/homework/tree/master/作业2

import urllib.request
from bs4 import BeautifulSoup
import sqlite3

# 定义爬取和解析网页的函数
def scrape_university_rankings(url):
    # 使用urllib获取网页内容
    with urllib.request.urlopen(url) as response:
        html_content = response.read()

    # 使用BeautifulSoup解析HTML
    soup = BeautifulSoup(html_content, 'html.parser')
    # 找到包含排名信息的表格
    table = soup.find('table')

    # 连接SQLite数据库(如果数据库不存在会自动创建)
    conn = sqlite3.connect('university_rankings.db')
    cursor = conn.cursor()

    # 创建表格(如果尚不存在)
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS rankings (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            ranking TEXT,
            university_name TEXT,
            province TEXT,
            type_of_university TEXT,
            total_score TEXT
        )
    ''')

    # 打印表头
    print("{:<10} {:<30} {:<10} {:<10} {:<10}".format("排名", "学校名称", "省市", "学校类型", "总分"))
    print("-" * 70)

    # 遍历表格的每一行
    for row in table.find_all('tr')[1:]:  # 跳过表头
        cols = row.find_all('td')
        ranking = cols[0].text.strip()
        # 只提取中文名称,跳过英文名称
        university_name = cols[1].text.split('\n')[0].strip()  # 假设中文名称在第一行
        province = cols[2].text.strip()
        type_of_university = cols[3].text.strip()
        total_score = cols[4].text.strip()

        # 打印每行的信息,使用格式化对齐
        print("{:<10} {:<30} {:<10} {:<10} {:<10}".format(ranking, university_name, province, type_of_university, total_score))

        # 插入数据到数据库
        cursor.execute('''
            INSERT INTO rankings (ranking, university_name, province, type_of_university, total_score)
            VALUES (?, ?, ?, ?, ?)
        ''', (ranking, university_name, province, type_of_university, total_score))

    # 提交更改并关闭连接
    conn.commit()
    conn.close()

# 爬取并打印大学排名信息
scrape_university_rankings('http://www.shanghairanking.cn/rankings/bcur/2021')

效果图:

心得体会:

使用urllib.request库轻松地从网页获取了内容,并借助BeautifulSoup解析HTML结构,这让我能够高效地定位和提取所需的数据。整个过程不仅加强了我对网络请求、HTML文档解析的理解,也提升了我的数据库操作技能,尤其是如何创建表以及执行SQL语句进行数据的插入。

分析过程:

总结与反思

作业反思

在完成本次作业的过程中,我遇到了一些挑战并学到了宝贵的经验。首先,在爬取中国气象网的7日天气预报时,由于网站结构较为复杂且部分数据是通过动态加载的,使用requests和BeautifulSoup直接解析HTML存在困难。此外,缺乏对网络请求异常的处理导致程序稳定性不足。其次,在爬取东方财富网股票信息时,要注意爬出的序号和文字的对应,否则对应不上,会爬取出错。最后,在视频转换gif时频频出错,如果有好用的软件请分享给我。

posted @ 2024-10-18 10:38  王贺雯  阅读(10)  评论(0编辑  收藏  举报