第二次作业


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

序号 地区 日期 天气信息 温度
1 北京 7日(今天) 晴间多云,北部山区有阵雨或雷阵雨转晴转多云 31℃/17℃
2 北京 8日(明天) 多云转晴,北部地区有分散阵雨或雷阵雨转晴 34℃/20℃
3 ... ... ... ...
1) 思路:
1.获取每个城市的编号,得到相应的url

在Network中找到存放城市及其编号的文件city.js,Request URL为https://j.i8tq.com/weather2020/search/city.js
2.解析网页得到数据


每个li标签对应一天的信息,通过soup.select("ul[class='t clearfix'] li")可全部获取
3.将数据保存到数据库

代码:

import requests,re
from bs4 import BeautifulSoup
import pymysql

# 获取城市对应的url
# 有些城市会重名,没重名不需要supcity参数,supcity是地区的上级地区,如:city=鼓楼,supcity可以为福州或福建
def getCityUrl(city, supcity=None):
    try:
        # 如果supcity不为None,则根据city和supcity进行匹配,得到只包含一个city的字符串
        msg = re.search(supcity + "(.|\n)*" + city + "(.|\n)*?},",r.text).group(0) if supcity else r.text
        # 单独匹配所需city
        s = re.search(city + "(.|\n)*?},", msg).group(0)
        # 提取s中的数字,即城市对应的编号
        num = re.search("\d+", s).group(0)
        return "http://www.weather.com.cn/weather/"+num+".shtml"
    except AttributeError as e:
        # 没匹配到就返回city不存在
        errmsg = supcity + city if supcity else city
        print(errmsg+"不存在!")

# 插入数据
def insertData(num, city, date, weather, temp):
    try:
        cursor.execute("insert into weathers(num, city, date, weather, temp)values (%s, %s, %s, %s, %s)",
                       (num, city, date, weather, temp))
        # 提交事务               
        db.commit()  
    except Exception as e:
        # 如果发生错误则输出错误信息并回滚
        print(e)
        db.rollback()  

# 存储数据
def saveData(cityurl, cityname):
    global t
    cr = requests.get(cityurl)
    cr.encoding = "UTF-8"
    soup = BeautifulSoup(cr.text, "html.parser")
    lis = soup.select("ul[class='t clearfix'] li")

    for li in lis:
        # li.text.split("\n")含有空字符串,除去就能得到所要数据
        data = [x for x in li.text.split("\n") if x != ""]
        print(mat.format(t, cityname, data[0], data[1], data[2]))
        insertData(t, cityname, data[0], data[1], data[2])
        t += 1

# 连接数据库
db = pymysql.Connect(
    host='localhost',
    port=3306,
    user='root',
    passwd='root',
    db='bai',
    charset='utf8'
)

# 获取游标
cursor = db.cursor()

# 表不存在则创建表
sql = """
         create table if not exists weathers (
         num int(10) primary key,
         city varchar(16),
         date varchar(16),
         weather varchar(64),  
         temp varchar(32))"""
cursor.execute(sql)

# 获取城市对应编号的url
url = "https://j.i8tq.com/weather2020/search/city.js"
r = requests.get(url)
# 城市集,有重名的用列表表示,福州可以替换成福建,江苏可以替换成南京
citys = ["泉州","稻城",["福州","鼓楼"],["江苏","鼓楼"],"桃花源"]
# 编号
t = 1
# 格式化输出
mat = "{:^4}\t{:^6}\t{:^8}\t{:^10}\t{:^8}"
print(mat.format("序号", "地区", "日期", "天气信息", "温度"))
for city in citys:
    # 根据str或list调用不同的方法,得到城市对应的url
    if type(city).__name__ == "str":
        cityurl = getCityUrl(city)
        cityname = city
    else:
        cityurl = getCityUrl(city[1], city[0])
        cityname = city[0]+city[1]
    if cityurl != None:
        saveData(cityurl, cityname)

# 关闭数据库连接
db.close()

运行结果:

2)心得体会:本实验难点主要是获取城市对应的编号,然后通过字符串拼接得到相应的url,后面想到有同名的地方,就增加了会重名地区的查询;然后解析网页获得数据,保存在数据库,第一次使用python连接MySQL,我的青春结束了.

作业②:
要求:用requests和BeautifulSoup库方法定向爬取股票相关信息。
输出信息:

序号 股票代码 股票名称 最新报价 涨跌幅 涨跌额 成交量 成交额 振幅 最高 最低 今开 昨收
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)思路:(只爬取沪深A股)
1.该网站通过createBody方法动态创建表格.通过Network寻找其获取数据的API,得到第一页的Request URL.


2.继续获取第二页和第三页的Request URL,探索该网站的翻页机制


可以看出,控制第几页的参数为pn,pn=1就是第一页
3.访问API,并解析出所要的数据

代码:

import requests,re
import json

# 计算有多少个中文字符,输出格式用到
def count(s):
    return len([ch for ch in s if '\u4e00' <= ch <= '\u9fff'])

cnt = 3  # 爬取页面数,最多210
# 输出表头
print("{:<3} {:<5} {:<6} {:<4} {:<5} {:<5} {:<8} {:<9} {:<4} {:<5} {:<4} {:<5} {:<5}".format(
    "序号", "股票代码", "股票名称", "最新报价", "涨跌幅", "涨跌额", "成交量", "成交额", "振幅", "最高", "最低", "今开", "昨收"))
for i in range(cnt):
    # 只对沪深A股进行爬取,利用参数pn实现翻页
    url = "http://41.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112408942134990117723_1601810673881&pn=" + \
        str(i+1)+"&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&fid=f3&fs=m:0+t:6,m:0+t:13,m:0+t:80,m:1+t:2,m:1+t:23"
    r = requests.get(url)
    r.encodingn = "UTF-8"
    # 找到第一个[的位置,因为前面有一个{,会对匹配造成影响
    text = r.text[r.text.index("["):]
    # 匹配所有{},每支股票信息都包含在一个{}里
    datas = re.findall("{.*?}", text)
    for j in range(len(datas)):
        # 将数据解析成字典
        data = json.loads(datas[j])
        # 输出数据
        temp = "{:<5} {:<8} {:<"+str(10-count(
            data['f14']))+"} {:<7} {:<7} {:<7} {:<8} {:<13} {:<6} {:<6} {:<6} {:<6} {:<6}"
        print(temp.format(i*20+j+1, data['f12'], data['f14'], data['f2'], data['f3'], data['f4'],
                          data['f5'], data['f6'], data['f7'], data['f15'], data['f16'], data['f17'], data['f18']))

运行结果:

2)心得体会:本实验所爬取的网站是动态加载的,需要我们去抓包分析找到json数据接口,分析翻页的参数等等,还是selenium香.

作业③:
根据自选3位数+学号后3位选取股票,获取印股票信息。
输出信息:

股票代码号 股票名称 今日开 今日最高 今日最低
605006 山东玻纤 9.04 8.58 8.13
1)代码:
import requests
import re

name = "振芯科技"
number = "300101"
# 同上,在Network中寻找js文件
url = "http://76.push2his.eastmoney.com/api/qt/stock/kline/get?cb=jQuery112409186255157892003_1601815696958&secid=0.300101" + \
"&ut=fa5fd1943c7b386f172d6893dbfba10b&fields1=f1%2Cf2%2Cf3%2Cf4%2Cf5%2Cf6&fields2=f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2" + \
"Cf58%2Cf59%2Cf60%2Cf61&klt=101&fqt=0&end=20500101&lmt=120&_=1601815696974"
r = requests.get(url)
r.encoding = "UTF-8"
# 选择最新时间的那条数据,数据包含在一对引号中,定位最后两个引号的位置,获取引号之间的数据
endOne = r.text.rindex("\"")
endTwo = r.text.rindex("\"", 0, endOne)
data = r.text[endTwo:endOne]
# 用,分隔得到一个数组,选择所需要的信息输出
data = data.split(",")

mat="{:<8}\t{:<8}\t{:<8}\t{:<8}\t{:<8}"

print(mat.format("股票代码号","股票名称", "今日开", "今日最高", "今日最低"))
print(mat.format(number,name,data[1],data[3],data[4]))

运行结果:

2)心得体会:同实验2抓包得到API,个人不是很懂股票,就取最新的日期对应的数据,不过最新日期是几天前的,不知道理解正确否?
待到山花烂漫时,她在丛中笑。秋天来了,zzp们的冬天还会远吗?

posted @ 2020-10-07 21:20  家住海边所以浪  阅读(161)  评论(0编辑  收藏  举报