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

发布时间 2023-10-07 20:38:55作者: kanata_konoe

作业①

实验内容

要求

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

输出信息

Gitee文件夹链接

代码

# Connect to database
conn = sqlite3.connect('weather.db')
cursor = conn.cursor()

# Check if table exists
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='WEATHER'")
table_exists = cursor.fetchone()

# Create table if it doesn't exist
if not table_exists:
    conn.execute('''CREATE TABLE WEATHER
           (ID INTEGER PRIMARY KEY AUTOINCREMENT,
           PLACE           TEXT    NOT NULL,
           DATE            TEXT    NOT NULL,
           WEATHER_INFO    TEXT    NOT NULL,
           TEMPERATURE     TEXT    NOT NULL);''')

conn.close()


def insert_weather_data(place, date, weather_info, temperature):
    # Connect to database
    conn = sqlite3.connect('weather.db')

    # Insert data into table
    conn.execute(f"INSERT INTO WEATHER (PLACE, DATE, WEATHER_INFO, TEMPERATURE) VALUES ('{place}', '{date}', '{weather_info}', '{temperature}')")

    # Commit changes and close connection
    conn.commit()
    conn.close()


url="http://www.weather.com.cn/weather/101010100.shtml"
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)
    data=data.read()
    dammit=UnicodeDammit(data,["utf-8","gbk"])
    data=dammit.unicode_markup
    soup=BeautifulSoup(data,"html.parser")
    lis=soup.select("ul[class='t clearfix'] li")
    place = soup.select("div[class='crumbs fl'] a")[1].text
    index = 1
    print(f"序号\t地区\t日期\t天气信息\t温度")
    for li in lis:
        try:
            date=li.select('h1')[0].text
            weather=li.select('p[class="wea"]')[0].text
            if li.select('p[class="tem"] span') == []:
                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(f"{index}\t{place}\t{date}\t{weather}\t{temp}")
            insert_weather_data(place, date, weather, temp)
            index += 1
        except Exception as err:
            print(err)
except Exception as err:
    print(err)

结果

实验心得

这个实验让我更加熟悉了Python网络爬虫的常用库的使用。同时,我还学到了如何连接和操作数据库,将获取到的数据存储在数据库中,以便后续的数据处理和分析。通过爬取网页上的天气数据,并将其保存在数据库中,我们可以方便地获取和管理大量的天气信息,为后续的数据分析和应用提供基础数据。

作业②

实验内容

要求

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

代码(省略数据库连接函数)

api = "https://93.push2.eastmoney.com/api/qt/clist/get"
parms = {
    "pn": "1",
    "pz": "20",
    "po": "1",
    "np": "1",
    "fltt": "2",
    "invt": "2",
    "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": "f12,f14,f2,f3,f4,f5,f6,f7,f15,f16,f17,f18",
    "_": "1696658826129"
}

key = {
    "f12": "代码",
    "f14": "名称",
    "f2": "最新价",
    "f3": "涨跌幅",
    "f4": "涨跌额",
    "f5": "成交量",
    "f6": "成交额",
    "f7": "振幅",
    "f15": "最高价",
    "f16": "最低价",
    "f17": "今开",
    "f18": "昨收",
}


limit = 100
count = 0
r = requests.get(api, params=parms)
json_data = r.json()["data"]
total = json_data["total"]

print("序号", end="\t")
for i in key.keys():
    print(key[i], end="\t")
print()
while count < limit and count < total:
    for i in json_data["diff"]:
        print(str(count + 1), end="\t")
        for j in key.keys():
            print(i[j], end="\t")
        insert_weather_data(i["f12"], i["f14"], i["f2"], i["f3"], i["f4"], 
                            i["f5"], i["f6"], i["f7"], i["f15"], i["f16"],
                            i["f17"], i["f18"])
        print()
        count += 1
        if count >= limit:
            break
    parms["pn"] = str(int(parms["pn"]) + 1)
    r = requests.get(api, params=parms)
    json_data = r.json()["data"]

结果

实验心得

这个实验让我更加熟悉使用开发者工具提取所需数据api的方法。我学到了如何根据不同的需求和情况调整API的请求参数,以获取所需的数据。同时,我也意识到了合理分析网页结构和抓包的重要性,这有助于我们理解网站的数据获取方式,并更好地进行定向爬取。这个实验不仅提升了我的网络爬虫技能,还为我进一步学习和应用数据分析提供了基础。

作业③

实验内容

要求

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

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

输出信息

Gitee文件夹链接

代码(省略数据库连接函数与字典信息)

url = 'https://www.shanghairanking.cn/_nuxt/static/1695811954/rankings/bcur/202311/payload.js'
r = requests.get(url, timeout=20)
if r.status_code == 200:
    r.encoding = 'utf-8'


# 变量字典映射
a = ()
b = ''
c = b.split(', ')
dic_tmp = dict(zip(c,a))

# 解析数据
datas = re.findall('\{(univUp.*?\})\}',r.text,re.S)
re_compair = r'univNameCn:"(.*)",univNameEn:(.*?),.*univTags:(.*],?),.*univCategory:(.*),province:(.*),score:(.*),ranking:(.*?),.*indData:{"411":(.*),"412":(.*),"413":(.*),"414":(.*),"415":(.*),"416":(.*),"417":(.*),"418":(.*),"419":(.*),"420":(.*)}'
dds = []
# 解析数据
for one_data in datas:
    dd = re.findall(re_compair,one_data,re.S)
    data_tmp = []
    for key in dd[0]:  
        if key in c:
            key = dic_tmp[key] 
        elif ']' in key:
            key_str = []
            key = key.replace('[','').replace(']','').split(',')
            if 'i' in key or 'l' in key or 'j' in key:
                for kk in key:
                    key_str.append(dic_tmp[kk])
            key = ','.join(key_str)        
        data_tmp.append(key) 
    dds.append(data_tmp)


print("排名", "学校", "省市", "类型", "总分", end="\t")
print()
for i in dds:
    insert_weather_data(i[6],i[0],i[4],i[3],i[5])
    print(i[6],i[0],i[4],i[3],i[5],end='\t')
    print()

结果

实验心得

实验3是耗时最长的一个实验,在抓取api数据时发现部分数据被混淆。结果分析在返沪的js头尾包含解码所需内容。

__NUXT_JSONP__("/rankings/bcur/202311", (function(...)))

...

("", false, null, 0, "理工", "综合",....)

两端内容为KV对,可以在组合后进行对混淆内容进行解码(混淆内容如下,b、a、e等字母可在字典中找到对应值)

{
    univUp: "xinjiang-institute-of-engineering",
    univLogo: "logo-jpg\u002F9851006000.jpg",
    univNameCn: "新疆工程学院",
    univNameEn: "Xinjiang Institute of Engineering",
    inbound: b,
    liked: b,
    univLikeCount: d,
    univTags: [],
    univNameRemark: a,
    univCategory: e,
    province: N,
    score: 85.2,
    ranking: oP,
    rankChange: c,
    rankOverall: oP,
    indData: {
        "411": a,
        "412": a,
        "413": a,
        "414": a,
        "415": a,
        "416": a,
        "417": a,
        "418": a,
        "419": a,
        "420": a
    }
}

这个实验让我更加熟悉了通过API来获取数据的方法,同时我也意识到了解码内容的重要性。