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

作业①

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

输出信息

序号 地区 日期 天气信息 温度
1 北京 7日(今天) 晴间多云,北部山区有阵雨或雷阵雨转晴转多云 31℃/17℃
2 北京 8日(明天) 多云转晴,北部地区有分散阵雨或雷阵雨转晴 34℃/20℃
3 北京 9日(后台) 晴转多云 36℃/22℃
4 北京 10日(周六) 阴转阵雨 30℃/19℃
5 北京 11日(周日) 阵雨 27℃/18℃
6......

Gitee 文件夹链接

码云链接

1).代码:

from bs4 import BeautifulSoup
from bs4 import UnicodeDammit
import urllib.request
import sqlite3

class WeatherDB:
    def openDB(self):
        self.con=sqlite3.connect("weathers.db")
        self.cursor=self.con.cursor()
        try:
            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:
            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={"北京":"101010100","上海":"101020100","广州":"101280101","深圳":"101280601"}

    def forecastCity(self,city):
        if city not in self.cityCode.keys():
            print(city+" code cannot be found")
            return

        url="http://www.weather.com.cn/weather/"+self.cityCode[city]+".shtml"
        try:
            req=urllib.request.Request(url,headers=self.headers)
            data=urllib.request.urlopen(req)
            data=data.read()
            dammit=UnicodeDammit(data,["utf-8","gbk"])
            data=dammit.unicode_markup
            soup=BeautifulSoup(data,"lxml")
            lis=soup.select("ul[class='t clearfix'] li")
            for li in lis:
                try:
                    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
                    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()
        self.db.openDB()

        for city in cities:
            self.forecastCity(city)
        #self.db.show()
        self.db.closeDB()

ws=WeatherForecast()
ws.process(["北京","上海","广州","深圳"])
print("completed")

结果:

2).心得体会:

第一个作业是对天气的复现作业,学习了如何创建与连接数据库、创建表,以及通过insert对表进行插入操作并且将表的内容打印出来。通过此次复现,对数据库有了一定的了解。

作业②

要求:用 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 文件夹链接

码云链接

首先通过f12进行抓包:

打开url查看:

1).代码:

利用request爬取数据并且通过json.loads提取数据:

for i in range(1, 10):
    url = 'http://2.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112407216976537918423_1695552655929&pn={}&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&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&_=1695552655930'.format(i)
    r = requests.get(url)
    r.raise_for_status()
    html = r.text
    # 去除非法字符
    valid_json = html.strip()[len('jQuery112407216976537918423_1695552655929('):-1]
    valid_json = valid_json[:-1]
    # 转换为json
    json_data = json.loads(valid_json)
    data = json_data['data']['diff']

创建表:

cursor.execute('''
    CREATE TABLE IF NOT EXISTS stocks (
        id INTEGER PRIMARY KEY,
        stock_code TEXT,
        stock_name TEXT,
        latest_price REAL,
        change_percent REAL,
        change_amount REAL,
        volume REAL,
        turnover REAL,
        amplitude REAL,
        highest REAL,
        lowest REAL,
        open_price REAL,
        close_price REAL
    )
''')

插入数据:

# 插入数据
    for item in data:
        cursor.execute('''
            INSERT INTO stocks (
                stock_code,
                stock_name,
                latest_price,
                change_percent,
                change_amount,
                volume,
                turnover,
                amplitude,
                highest,
                lowest,
                open_price,
                close_price
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ''', (
            item['f12'],
            item['f14'],
            item['f2'],
            item['f3'],
            item['f4'],
            item['f5'],
            item['f6'],
            item['f7'],
            item['f15'],
            item['f16'],
            item['f17'],
            item['f18']
        ))
        count += 1

输出数据:

# 打印数据
cursor.execute('SELECT * FROM stocks')
rows = cursor.fetchall()
for row in rows:
    print(row)

结果:

2).心得体会:

本次实验是第一尝试抓包并且通过json进行数提取数据的,但最开始时遇到以下报错:

通过实验发现是因为url里面一些内容是非法字符,json无法解析,通过删除便解决了这个问题。

通过此次实验对抓包和数据库有了一定的了解。

作业③:

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

技巧:分析该网站的发包情况,分析获取数据的api

输出信息:

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

Gitee****文件夹链接

码云链接

通过f12进行抓包:

先找到对应的payloads.js

点击进去虽然是乱码,但可以通过html.text进行解析

1).代码:
因为通过我的方法,省份和类型无法直接提取出来,所以需要先通过字典进行保存之后再进行映射:

# 创建省份和大学类别的字母映射字典
province_mapping = {
    'k': '江苏','n': '山东', 'o': '河南','p': '河北','q': '北京','r': '辽宁','s': '陕西','t': '四川','u': '广东',
    'v': '湖北','w': '湖南','x': '浙江','y': '安徽','z': '江西','A': '黑龙江','B': '吉林','C': '上海','D': '福建','E': '山西',
    'F': '云南','G': '广西','I': '贵州','J': '甘肃','K': '内蒙古','L': '重庆','M': '天津','N': '新疆','Y': '海南'
}

univ_category_mapping = {
    'f': '综合',
    'e': '理工',
    'h': '师范',
    'm': '农业',
    'T': '林业',
}

利用request和正则表达式进行数据提取:

url = 'https://www.shanghairanking.cn/_nuxt/static/1695811954/rankings/bcur/2021/payload.js'
header = {
    "User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre"
}
resp = requests.get(url, headers=header)
resp.raise_for_status()
resp.encoding = resp.apparent_encoding
html = resp.text

rname = 'univNameCn:"(.*?)"'
rscore = 'score:(.*?),'
rprovince = 'province:(.*?),'
runivCategory = 'univCategory:(.*?),'
namelist = re.findall(rname, html, re.S | re.M)
scorelist = re.findall(rscore, html, re.S | re.M)
provincelist = re.findall(rprovince, html, re.S | re.M)
univCategorylist = re.findall(runivCategory, html, re.S | re.M)

创建数据库与表:

# 创建或连接到数据库
conn = sqlite3.connect('university_rankings.db')
cursor = conn.cursor()
# 创建表格,如果不存在
cursor.execute('''
    CREATE TABLE IF NOT EXISTS university_rankings (
        rank INTEGER,
        name TEXT,
        province Text,
        univCategory Text,
        score REAL
    )
''')

插入数据:

# 插入数据到数据库,将字母映射为具体内容
for rank, (name, province_letter, univCategory_letter, score) in enumerate(zip(namelist,  provincelist, univCategorylist, scorelist), start=1):
    try:
        score_float = float(score)
    except ValueError:
        # 如果无法转换为浮点数,将分数设为 None
        score_float = None

    # 使用映射字典将字母替换为具体内容
    province = province_mapping.get(province_letter, province_letter)
    univCategory = univ_category_mapping.get(univCategory_letter, univCategory_letter)

    cursor.execute("INSERT INTO university_rankings (rank, name, province, univCategory, score) VALUES (?, ?, ?, ?, ?)",
                   (rank, name, province, univCategory, score_float))

保存到excel中:

# 从数据库中检索数据
conn = sqlite3.connect('university_rankings.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM university_rankings")
data = cursor.fetchall()
conn.close()
# 创建一个DataFrame对象
df = pd.DataFrame(data, columns=["Rank", "Name", "Province", "UnivCategory", "Score"])
# 保存数据到Excel文件
excel_file = "university_rankings.xlsx"  # 指定Excel文件名
df.to_excel(excel_file, index=False)  # 将DataFrame保存为Excel文件,不包括索引列
print("数据已保存到 Excel 文件:", excel_file)

结果:

2).心得体会:

本次实验仍是抓包与数据库,但我将本题的结果从数据库中提取出来然后保存在excel中,通过此次实验,我更加深刻地理解了抓包与数据库、表的创建和数据的插入。

posted @ 2023-10-07 19:40  qxt0320  阅读(100)  评论(0)    收藏  举报