数据采集与融合第二次作业——董婕

作业1

要求

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

输出信息

gitee链接

https://gitee.com/djj031217/djj/blob/master/数据采集与融合技术第二次作业/实验2 1.py

实现过程

在搜索框搜索想要查找的城市

点进去后在这里可以找到各个城市与数字的对应关系,将其添加到代码中即可。

代码

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 NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362"}
        # "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 = {"安徽": "101220101", "黄山": "101221001", "广州": "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

要求

  1. 用 requests 和 BeautifulSoup 库方法定向爬取股票相关信息,并存储在数据库中。
  2. 候选网站:东方财富网:https://www.eastmoney.com/
    新浪股票:http://finance.sina.com.cn/stock/
  3. 技巧:在谷歌浏览器中进入 F12 调试模式进行抓包,查找股票列表加载使用的 url,并分析 api 返回的值,并根据所要求的参数可适当更改api 的请求参数。根据 URL 可观察请求的参数 f1、f2 可获取不同的数值,根据情况可删减请求的参数。
  4. 参考链接:https://zhuanlan.zhihu.com/p/50099084

输出信息:

gitee链接

https://gitee.com/djj031217/djj/blob/master/数据采集与融合技术第二次作业/实验2 2.py

实现过程

观察数据结构可发现

  1. 参数pn会随着页数的增加而增加,故pn即页码
  2. fields参数对应的是列信息
  3. 同一只股票的fs相同,fs代表的是股票信息

代码

import requests
import re
import xlsxwriter

# 定义函数,用于获取页面数据
def getHTML(fs, page):
    pz = 20
    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"
    url = "http://58.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112409968248217612661_1601548126340&pn=" + str(page) + \
          "&pz=" + str(pz) + "&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&fid=f3&fs=" + fs["沪深A股"] + \
          "&fields=" + fields + "&_=1601548126345"

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.63"}

    try:
        res = requests.get(url, headers=headers)

        pat = '"diff":\[(.*?)\]'
        data = re.compile(pat, re.S).findall(res.text)
        datas = data[0].split("},{")
        return datas
    except:
        print('wrong url')

# 定义函数,用于创建Excel文件的标题行
def create_Header(workbook):
    worksheet = workbook.add_worksheet()

    bold = workbook.add_format({'bold': True, 'font_color': 'red', 'align': 'center'})

    worksheet.write('A1', '代码', bold)
    worksheet.write('B1', '名称', bold)
    worksheet.write('C1', '最新价', bold)
    worksheet.write('D1', '涨跌幅', bold)
    worksheet.write('E1', '涨跌额', bold)
    worksheet.write('F1', '成交量', bold)
    worksheet.write('G1', '成交额', bold)
    worksheet.write('H1', '涨幅', bold)
    worksheet.set_column('A:A', 10)
    worksheet.set_column('B:B', 10)
    worksheet.set_column('C:C', 8)
    worksheet.set_column('D:D', 8)
    worksheet.set_column('E:E', 8)
    worksheet.set_column('F:F', 10)
    worksheet.set_column('G:G', 16)
    worksheet.set_column('H:H', 8)
    return worksheet

# 定义函数,用于将页面数据写入Excel文件
def getPageData(datas, row):
    col = 0
    for i in range(len(datas)):
        datas1 = datas[i].split(",")
        Number = eval(datas1[11].split(":")[1])
        Name = eval(datas1[13].split(":")[1])
        Newest_price = eval(datas1[1].split(":")[1])
        updownExtent = eval(datas1[2].split(":")[1])
        updownValue = eval(datas1[3].split(":")[1])
        Money_number = eval(datas1[4].split(":")[1])
        Money = eval(datas1[5].split(":")[1])
        Up_number = eval(datas1[6].split(":")[1])
        worksheet.write(row, col, Number)
        worksheet.write(row, col + 1, Name)
        worksheet.write(row, col + 2, Newest_price)
        worksheet.write(row, col + 3, updownExtent)
        worksheet.write(row, col + 4, updownValue)
        worksheet.write(row, col + 5, Money_number)
        worksheet.write(row, col + 6, Money)
        worksheet.write(row, col + 7, Up_number)
        row += 1

if __name__ == '__main__':
    fs = {
        "沪深A股": "m:0+t:6,m:0+t:13,m:0+t:80,m:1+t:2,m:1+t:23"
    }
    page = 4
    row = 1
    name = "股票"
    workbook = xlsxwriter.Workbook(name + '.xlsx')
    worksheet = create_Header(workbook)
    for p in range(page):
        datas = getHTML(fs, p + 1)
        getPageData(datas, row)
        row += 20
    print("\n存储成功!")
    workbook.close()
    print("\n爬取结束")

结果

心得

本次作业与之前不太一样,东方财富网页面所包含的股票信息被分成了多个板块,我们无法直接通过网页的url爬取所有数据,故本题采用动态抓包,使用f12进行抓包抓取json并分析得到数据对应的url。

作业3

要求

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

输出信息

gitee链接

https://gitee.com/djj031217/djj/blob/master/数据采集与融合技术第二次作业/实验2 3.py

实现过程

演示视频

很容易找到学校名称和分数的信息,但省份和学校类别的信息是在头尾的键值对里的,一开始没注意,找了挺久的。
故需要添加键值对的映射,省份和类别映射如下

category = {
    'e': '理工',
    'f': '综合',
    'h': '师范',
    'm': '农业',
    'T': '林业',}
province = {
    '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': '海南'
}

代码

import re
import requests
import pandas as pd
import pymysql
# 创建大学类别的字母映射字典
category = {
    'f': '综合',
    'e': '理工',
    'h': '师范',
    'm': '农业',
    'T': '林业',
}
# 创建省份字母映射字典
province = {
    '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': '海南'
}
url = 'https://www.shanghairanking.cn/_nuxt/static/1697106492/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

# 编译正则表达式
obj = re.compile(
    r'univNameCn:"(?P<univNameCn>.*?)",.*?'
    r'univCategory:(?P<univCategory>.*?),.*?'
    r'province:(?P<province>.*?),'
    r'score:(?P<score>.*?),'
    , re.S)

result1 = obj.finditer(resp.text)
results = []

# 遍历正则匹配的结果
for idx, it in enumerate(result1, start=1):
    univNameCn = it.group('univNameCn')
    univCategory = it.group('univCategory')
    province_code = it.group('province')
    score = it.group('score')

    # 使用字典进行映射转换
    mapped_province = province.get(province_code, province_code)  # 如果找不到映射,则使用原始值
    mapped_category = category.get(univCategory, univCategory)  # 如果找不到映射,则使用原始值

    results.append((idx, univNameCn, mapped_province, mapped_category, score))

# 使用pandas创建DataFrame
df = pd.DataFrame(results, columns=['排名', '学校', '省市', '类型', '总分'])

# 连接到MySQL数据库
db = pymysql.connect(host='localhost', user='root', password='1', database='dong')
cursor = db.cursor()

# 将DataFrame中的数据插入到MySQL数据库表中
for index, row in df.iterrows():
    sql = "INSERT INTO 22 (排名, 学校, 省市, 类型, 总分) VALUES (%s, %s, %s, %s, %s)"
    cursor.execute(sql, (row['排名'], row['学校'], row['省市'], row['类型'], row['总分']))

# 提交更改并关闭数据库连接
db.commit()
db.close()

# 保存DataFrame为Excel文件
df.to_excel('universities.xlsx', index=False)

结果

在navicat储存

心得

1.学会了一种新的方式获取数据,先抓包,再分析包中的数据。
2.重新复习了mysql的一些语法,并意识到要仔细观察数据结构,比如前后的键值对映射关系

posted @ 2023-10-17 17:44  LLLL2  阅读(46)  评论(0)    收藏  举报