python学习笔记 2 - 网络爬虫

用python对页面进行爬取

例 1

以下是一个简单的python爬取demo,将url中的内容存储到bridge.png中:

import requests
import json

if __name__ == '__main__':
    url = 'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF'
    req = requests.get(url)
    f = open('bridge.png', 'wb')
    f.write(req.content)
    f.close()

例 2

下面我们爬取以下更复杂一些的数据:

import requests
import json

import numpy as np
import pandas as pd

if __name__ == '__main__':
    url_someStock = 'https://q.stock.sohu.com/hisHq?code=cn_300985&start=20210429&end=20210813&stat=1&order=D&period=d&callback=historySearchHandler&rt=jsonp&r=0.669360311489062&0.925820289825436'
    response = requests.get(url_someStock)
    data = response.text
    start = data.find('{')
    end = data.find('}')
    data = data[start:end+1]

url_someStock里面,即我们的数据,这是一个关于股票某短时间内的历史行情的数据,我们通过requests读取这组数据后,找到两个大括号,中间的内容,就是我们一行json格式数据的内容。

数据的json格式如下图,一组数据包括日期、开盘、收盘、涨跌额、涨跌幅、最低、最高、成交量(手)、成交金额(万)、换手率、盘后量(手):
在这里插入图片描述

    data = json.loads(data)
    data = data['hq']
    data = np.array(data)
    np.set_printoptions(linewidth=500)
    data = data[:, [0,1,2,5,6,7,8]]
    print(data)

使用json.loads()函数,将json格式数据转换为字典,而data[‘hq’]中的内容就是我们需要的具体行情信息,是一个list格式。将这个list转化为一个numpy.array便于后续操作。
第4行的意思是在输出时一行允许输出内容上限为500个字符(因为数据较长,一组数据超过了默认的80个字符)。
第5行的冒号的意思是输出array中的每一行数据,冒号后面的[0,1,2,5,6,7,8]表示输出第0,1,2,5,6,7,8列数据,输出格式如下图(如果没有第4行,则每行数据会从中间换行):
在这里插入图片描述

    data = pd.DataFrame(data, columns=['日期', '开盘', '收盘', '最低', '最高', '成交量(手)', '成交金额(万)'])
    data.sort_values(by=['日期'], inplace=True, ascending=True)
    data.set_index(keys=['日期'], inplace=True)
    data.to_excel('stock300985.xlsx')

通过pandas将刚才的数据转换成一个DataFrame格式,并以日期为索引:
在这里插入图片描述
这里的inplace=True的意思是在原数据上进行排序,inplace的默认值是False,使用方式是:

	t = data.set_index()

这样的话t里面就是排列后的结果,而data里数据不变。

例 3

第三个例子我们来尝试爬取一下新冠疫情的全球数据。
首先我们从这个网站爬取。
在页面任意位置右键点击检查,点击Networks后刷新页面,即可获取页面网络数据:
在这里插入图片描述
在右侧列表中找有可能的数据,一般看看文件名和文件格式就可以确定了。点击数据后,可以点击Response查看具体数据内容,然后复制Headers中的网址,这个网址就是我们需要的数据了。
在这里插入图片描述
数据格式如下:
在这里插入图片描述
我们需要的数据是areaTree里的全球数据。获取代码如下:

import json
import requests
import pandas as pd

if __name__ == '__main__':
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
    }
    url = 'https://c.m.163.com/ug/api/wuhan/app/data/list-total?t=325820807889'
    r = requests.get(url, headers=headers)
    data_json = json.loads(r.text)
    data = data_json['data']
    areaTree = data['areaTree']

获取数据后,我们需要摘取其中用的到的数据存储下来,获取数据的函数get_data如下,这个函数的输入为刚才的areaTree和我们需要的数据名称形成的list,并且获取数据中today标签下的数据(第2行),将数据列命名修改为“today_+原命名”(第3行),info中存储了info_list里我们需要的内容(第8行):

def get_data(data, info_list):
    today_data = pd.DataFrame([d['today'] for d in data])
    today_data.columns = ['today_' + i for i in today_data.columns]

    total_data = pd.DataFrame([d['total'] for d in data])
    total_data.columns = ['total_' + i for i in total_data.columns]

    info = pd.DataFrame(data)[info_list]  # 主要信息
    return pd.concat([info, total_data, today_data], axis=1)  # 按照列合并

获取数据后,我们使用函数save_data,存储数据,函数如下:

def save_data(data, name):
    file_name = name + '_' + time.strftime('%Y_%m_%d', time.localtime(time.time())) + '.csv'
    data.to_csv(file_name, index=None, encoding='utf_8_sig')
    print(file_name + ' 保存成功!')

在主函数中调用这两个函数:

    today_world = get_data(areaTree, ['id', 'lastUpdateTime', 'name'])
    save_data(today_world, 'today_world')

一些附加内容

刚才我们已经获得了数据today_world_2021_08_16.csv,现在输入以下代码:

import pandas as pd

if __name__ == '__main__':
    pd.set_option('display.min_rows', 10)
    pd.set_option('display.width', 1000)
    pd.set_option('display.max_columns', 20)
    data = pd.read_csv("today_world_2021_08_16.csv")
    print(data['name', 'total_confirm'])

结果会报错,最后一行的写法是错误的,我的原意是输出“name”和“total_confirm”两列的内容,但是最后一行的写法,python会认为我要找一行名为“‘name’, ‘total_confirm’”的数据。正确写法应该是:

    print(data[['name', 'total_confirm']])

还可以做以下的打印操作:

    print(data.head(10))          # 获取前10
    print(data.tail(10))          # 获取后10个
    print(data.sample(10))        # 随机获取10个
    print(data.iloc[2:5, 4:9])    # 获取第2行到第5行,第4列到第9列内容
    print(data.iloc[:5, 'name'])  # 获取前5行,列名为name的内容

可视化

现在我们来做一个可视化的疫情图表:

import matplotlib.pyplot as plt
import matplotlib as mpl

    data.sort_values(by='total_confirm', inplace=True, ascending=False)
    d = data[['name', 'total_confirm']]
    d = d.iloc[:10, :]
    mpl.rcParams['font.sans-serif'] = ['fangsong']
    mpl.rcParams['axes.unicode_minus'] = False
    plt.figure(figsize=(8, 6))
    plt.bar(d['name'], d['total_confirm'], width=0.75, color='y')
    plt.xlabel('国家')
    plt.ylabel('确诊人数', fontsize=15)
    plt.title('新冠确诊数量前十国家', fontsize=20)
    plt.show()

效果如图:
在这里插入图片描述

zip函数

zip函数的作用是把两组数据一一对应的关联起来,输入以下代码:

    name = 'n1', 'n2', 'n3', 'n4', 'n5'
    num = [100, 0], [200, 20], [123, 345], [222, 43], [12, 56]
    print(list(zip(name, num)))
    print(dict(zip(name, num)))
    print(pd.DataFrame(dict(zip(name, num))))

输出结果:
在这里插入图片描述

今天大概就讲到这里,后面有时间的话在尝试用beautiful soup获取标准化数据进行爬取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值