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

发布时间 2023-10-08 18:15:56作者: leo102102119

作业一:

要求:

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

输出信息:

Gitee文件夹链接

实验:

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()
        i=1
        print("{:4}\t{:10}\t{:14}\t{:24}\t{:16}".format("序号","城市", "日期", "天气信息", "温度"))
        for row in rows:
            print("{:4}\t{:10}\t{:10}\t{:24}\t{:16}".format(i,row[0], row[1], row[2], row[3]))
            i+=1
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") #找到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 #温度
                    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")

结果:

心得体会:

本次实验我使用了urllib和bs4库完成对信息的爬取,难点在于多页爬取。主要的解决方法是:一是查找数据接口,找到不同数据页面所需要的请求格式,二是使用selenium找到解析html源码,找到按钮标签。

作业二:

要求:

用requests和自选提取信息方法定向爬取股票相关信息,并存储在数据库中。

输出信息:

Gitee文件夹链接

实验:

import requests
import re
import math
#用get方法访问服务器并提取页面数据
def getHtml(fs,page,k):
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.8 Safari/537.36}"
    }
    #页数是通过修改pn值,不同股票的url有两个地方不同,通过之后的字典来实现。
    url = "http://35.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112402976183355999211_1601533720950&pn="+str(page)+"&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&fid=f3&fs="+fs+"&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&_="+k
    r = requests.get(url,headers=headers)
    pat = "\"data\":.*\]"
    data = re.compile(pat, re.S).findall(r.text)
    # 获取数据总条数,用于主函数中计算总页数,每页有20条数据,相除向上取整为总页数。
    t=re.findall(r"\"total\":[\d]*",data[0])
    to=t[0].split(':')
    total=eval(to[1])
    # 去除前面的total和diff数据
    data[0]=data[0][29:]
    return data,total
#获取单个页面股票数据
def getOnePageStock(fs,page,k,number,i):
    data = getHtml(fs,page,k)
    data=data[0]
    datas = data[0].split('},{') #不同股票分割
    stocks = []
    find=0  #设置find来判断是否找到了
    for t in range(len(datas)):
        stock = datas[t].replace('"',"").split(',')#不同信息分割,并且去掉引号
        for j in range(len(stock)):
            # 冒号分割,获取信息的值
            t=stock[j].split(':')
            stock[j]=t[1]
        if stock[11] == number:
            stocks.append(stock)
            find=1 #找到,就可以输出,停止循环了
            print(i)
            print("在第"+str(page)+"页:")
            print("{:4}\t{:4}\t{:4}\t{:4}\t{:4}\t{:4}\t{:4}\t{:4}".format("代码", "名称", "今开", "最高", "最低","涨跌幅","换手率","成交量"))
            print("{:4}\t{:4}\t{:4}\t{:4}\t{:4}\t{:4}\t{:4}\t{:4}".format(stock[11],stock[13],stock[16],stock[14],stock[15],stock[2],stock[7],stock[4]))
            break
    return find
def main():
    fs = {
        "沪深A股":"m:0+t:6,m:0+t:13,m:0+t:80,m:1+t:2,m:1+t:23",
        "上证A股":"m:1+t:2,m:1+t:23",
        "深证A股":"m:0+t:6,m:0+t:13,m:0+t:80",
        "新股":"m:0+f:8,m:1+f:8",
        "中小板":"m:0+t:13",
        "创业板":"m:0+t:80"
    }
    k = {
        "沪深A股": "1601536578738",
        "上证A股": "1601536578736",
        "深证A股": "1601536578759",
        "新股": "1601536578765",
        "中小板": "1601536578882",
        "创业板": "1601536578888"
    }
    #自选三位加学号后三位
    number='603119'
    for i in fs.keys():
        page = 1
        iffind = getOnePageStock(fs[i],page,k[i],number,i)
        #计算总页数
        total=getHtml(fs[i], 1, k[i])
        totalpage=math.ceil(total[1]/20.0)
        #自动爬取多页
        while True:
            page += 1
            if page <= totalpage and iffind !=1: #如果小于总页数,并且没找到,就继续找
                iffind=getOnePageStock(fs[i], page,k[i],number,i)
                #print(i+"已加载第"+str(page)+"页")
            else:
                break
main()

结果:

心得体会:

本次任务requests和自选提取信息方法定向爬取股票相关信息,并存储在数据库中。通过这个任务,我掌握了REQUEST库和GET方法。我开始觉得任务十分困难,后来,在同学的帮助下,我成功爬取了网页。

作业三:

要求:

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

技巧:

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

输出信息:

Gitee文件夹链接

实验:

import requests  # 方式1获取URL信息
import urllib.request  # 方式2获取URL信息
from bs4 import BeautifulSoup
import bs4
# 从网络上获取大学排名网页内容。
def getHTMLText(url):  # 获取URL信息,输出内容
    # =========================方式1获取=========================
    try:
        res = requests.get(url)  # 使用requests库爬取
        res.raise_for_status()  # 产生异常信息
        res.encoding = res.apparent_encoding  # 修改编码
        return res.text  # 返回网页编码
    except Exception as err:
        print(err)
    # =========================方式2获取=========================
    try:
        req = urllib.request.Request(url)
        # 打开URL网站的网址,读出二进制数据,二进制数据转为字符串
        data = urllib.request.urlopen(req).read.decode()
        return data
    except Exception as err:
        print(err)
# 提取网页内容中信息到合适的数据结构.
def fillUnivList(ulist, html):  # 将html页面放到ulist列表中(核心)
    # 解析网页文件(使用html解释器)
    soup = BeautifulSoup(html, "html.parser")
    # soup.prettify()  # 把soup对象的文档树变换成一个字符串
    # 数据结构:所用数据都封装在一个表格(标签tbody)中,单个学校信息在tr标签中,详细信息在td标签中
    # 学校名称在a标签中,定义一个列表单独存放a标签内容
    for tr in soup.find('tbody').children:
        if isinstance(tr, bs4.element.Tag):  # 如果tr标签的类型不是bs4库中定义的tag类型,则过滤掉
            a = tr('a')  # 把所用的a标签存为一个列表类型
            tds = tr('td')  # 将所有的td标签存为一个列表类型
            ulist.append([tds[0].text.strip(), a[0].string.strip(), tds[2].text.strip(),
                          tds[3].text.strip(), tds[4].text.strip()])
            # 使用strip()函数,它的作用是用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
# 利用数据结构展示并输出结果:定义函数
def printUnivList(ulist1, num):  # 打印出ulist列表的信息,num表示希望将列表中的多少个元素打印出来
    # 格式化输出
    tplt = "{0:^10}\t{1:^10}\t{2:^12}\t{3:^12}\t{4:^10}"
    print(tplt.format("排名", "学校名称", "省份", "学校类型", "总分"))
    for i in range(num):
        u = ulist1[i]
        print(tplt.format(u[0], u[1], u[2], u[3], u[4]))
def main():
    uinfo = []  # 将大学信息放到列表中
    url = "https://www.shanghairanking.cn/rankings/bcur/2021"
    html = getHTMLText(url)
    fillUnivList(uinfo, html)
    printUnivList(uinfo, 25)  # 一个界面的数据
if __name__ == '__main__':
    main()

结果:

心得体会:

本次实验我使用了urllib和bs4库完成对大学排名信息的爬取,难点在于多页爬取。主要的解决方法是:一是查找数据接口,找到不同数据页面所需要的请求格式,二是使用selenium找到解析html源码,找到按钮标签。