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

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

作业①

要求:在中国气象网(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 ......

1)完成过程:

1.通过浏览器查看网址内容并找到要爬取的信息

2.检查元素,观察相关信息所在位置

  • 对着元素右键选择检查即可查看该信息在html文档中的位置,简单锁定想寻找的标签

3.根据信息所在标签进行爬取

  • 可以看到搜索结果正确,前七项即为所需的七日天气预报数据
  • 将标签下的文本划分后即为包含了除城市名外的所有信息(真是方便啊)

4.简单清洗下数据

  • 可以看到爬取的信息中风力是不需要的,且没有城市名,那么去除风力信息再加上城市名即可

5.结果存入数据库并打印输出

  • 数据库相关操作都是在老师发的样例函数上做的修改,没啥好说的~
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 Exception as 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" % ("地区", "日期", "天气信息", "温度"))  # 表头
        for row in rows:
            print("%-16s%-16s%-32s%-16s" % (row[0], row[1], row[2], row[3]))
  • 最后结果如下啦:

2)心得体会:

还是中规中矩的作业,多利用检查和浏览器F12很快就能找到所需数据啦,多的就是熟悉了通过数据库将爬取的数据保存在本地,还是很有收获的!

作业②

  • 要求:用requests和BeautifulSoup库方法定向爬取股票相关信息。
  • 候选网站:东方财富网:http://quote.eastmoney.com/center/gridlist.html#hs_a_board
  • 技巧:在谷歌浏览器中进入F12调试模式进行抓包,查找股票列表加载使用的url,并分析api返回的值,并根据所要求的参数可适当更改api的请求参数。根据URL可观察请求的参数f1、f2可获取不同的数值,根据情况可删减请求的参数。
  • 参考链接:https://zhuanlan.zhihu.com/p/50099084
  • 输出信息:
序号 股票代码 股票名称 最新报价 涨跌幅 涨跌额 成交量 成交额 振幅 最高 最低 今开 昨收
1 688093 N世华 28.47 62.22% 10.92 26.13万 7.6亿 22.34 32.0 28.08 30.2 17.55
2 ...

1)完成过程:

1.看看网站长什么样子

2.检查检查数据藏在哪~

  • 数据是通过json包加载出来的,所以这次的爬取对象变成了js文件的url

3.分析数据结构

  • 爬下来的数据是json格式,和以往结构不同,同时键名也不直接是所需属性的名称,而是存在位置的映射关系
  • 先截取其中一项完整的数据
  • 再根据原网页中的属性值进行匹配
    利用CTRL+F进行搜索可以快速找到对应值,例如下图可知最新价对应的键名是f2

4.爬取相应数据并清洗

  • 使用对应正则匹配式匹配对应属性值,再将字符串进行清洗,同时对部分属性进行特殊处理
info1_Re = r'f12":".*?"'
info2_Re = r'f14":".*?"'
info3_Re = r'f2":.*?,'
info4_Re = r'f3":.*?,'
info5_Re = r'f4":.*?,'
info6_Re = r'f5":.*?,'
info7_Re = r'f6":.*?,'
info8_Re = r'f7":.*?,'
info9_Re = r'f15":.*?,'
info10_Re = r'f16":.*?,'
info11_Re = r'f17":.*?,'
info12_Re = r'f18":.*?,'
info1 = re.findall(info1_Re, resp)
info2 = re.findall(info2_Re, resp)
info3 = re.findall(info3_Re, resp)
info4 = re.findall(info4_Re, resp)
info5 = re.findall(info5_Re, resp)
info6 = re.findall(info6_Re, resp)
info7 = re.findall(info7_Re, resp)
info8 = re.findall(info8_Re, resp)
info9 = re.findall(info9_Re, resp)
info10 = re.findall(info10_Re, resp)
info11 = re.findall(info11_Re, resp)
info12 = re.findall(info12_Re, resp)

infos = []  # 存储各行信息
for index in range(len(info1)):
    info = []  # 存储单行信息
    # 对各项数据进行清洗
    for i in range(1, 3):
        info.append(eval('info' + str(i))[index].split('"')[-2])
    for i in range(3, 13):
        if i not in [4, 8]:
            info.append(eval('info' + str(i))[index].replace(',', '').split(':')[-1])
        else:
            info.append(eval('info' + str(i))[index].replace(',', '').split(':')[-1] + '%')
    infos.append(info)

for i in range(len(infos)):  # 将成交量与成交额转换成以亿、万为单位的格式
    a = eval(infos[i][5])  # 先转化为数值形式
    if a > 100000000:  # 符合条件则转换并添加单位
        a = round(a / 100000000, 2)
        a = str(a) + '亿'
    elif a > 10000:
        a = round(a / 10000, 2)
        a = str(a) + '万'
    else:
        a = str(a)
    infos[i][5] = str(a)

    a = eval(infos[i][6])
    if a > 100000000:
        a = round(a / 100000000, 2)
        a = str(a) + '亿'
    elif a > 10000:
        a = round(a / 10000, 2)
        a = str(a) + '万'
    else:
        a = str(a)
    infos[i][6] = a
  • 清洗结果如下:

5.结果存入数据库及打印展示

  • 相关代码与作业①基本一致不做赘述

2)心得体会:

本次作业流程与之前又有所不同,爬取的json包中数据并非赤裸裸展示,而是具有隐式映射关系,匹配关系时需要小心谨慎,同时需要注意股票信息实时更新,会出现网页值与先前爬好的数据不一致的情况,需要自己把握大约值并且尽快配对。

作业③

  • 要求: 爬取中国大学2021主榜 https://www.shanghairanking.cn/rankings/bcur/2021
    所有院校信息,并存储在数据库中,同时将浏览器F12调试分析的过程录制Gif加入至博客中。
  • 技巧: 分析该网站的发包情况,分析获取数据的api
  • 输出信息:
排名 学校 总分
1 清华大学 969.2

1)完成过程:

1.继续看看网站长什么样

  • 十分熟悉的老朋友

2.这次要求有所不同,需要所有大学的信息,因此需要从json文件中获取

3.试着爬爬先

  • 爬下来的数据很是奇怪!

4.分析分析数据

  • 先看看单项数据是什么情况
  • 要找的属性都在,但有的属性值却让人头很大!这个e$换成1该有多好
  • 但网页中确实有显示正确排名,用CTRL+F来找找正确的数据吧
  • 排名数据'1'存在的地方太多,检查发现其他排名也都是不知所云的数据,那么用最后一名582来试试
  • 如此多的数据真实值排列在文档尾端我相信这不是巧合!
  • 同时还发现清华大学的排名e$出现在文档头部,且存在大量类似结构
  • 通过爬取头尾两个字段并进行比较验证,发现这是他们可以组成一组键值对映射文档数据中的真实值!
  • 将value第一项""去除即可组成可使用的字典以翻译文档中的数据
  • 生成字典

5.数据清洗

  • 配合设置好的字典将爬取的字段进行翻译,结果如下
  • 数据中只有排名211与字典相差一位,没能找出原因,最后当作特值特殊处理

6.存入数据库与打印输出

  • 该部分与作业①类似不做赘述

2)心得体会:

作业③在作业②的基础上更近一筹,越来越有破译密码的味道,虽然这种感觉很可能是因为我学的太少才会产生,但成功后确实让人振奋。

代码

posted @ 2021-10-19 00:50  Poootato  阅读(36)  评论(0编辑  收藏  举报