【网络爬虫篇】数据采集技术综合项目实战2(协程式网络爬虫+数据预处理+数据可视化)附带详细步骤说明,干货满满

 更多优秀文章借鉴:

1. 使用Selenium实现黑马头条滑块自动登录

2. 使用多线程采集爬取豆瓣top250电影榜

3. 使用Scrapy爬取去哪儿网游记数据 

4. 数据采集技术综合项目实战1:国家水稻网数据采集与分析

5. 数据采集技术综合项目实战2:某东苹果15数据采集与分析

6. 数据采集技术综合案例实战3:b站弹幕采集与分析

导航小助手

1. 数据采集部分:

1.1 目标网址:

1.2 https://item.jd.com/100066896338.html#none

1.3 爬虫思路分析:

1.4 结果演示:

1.5 结论:

2. 数据预处理部分:

2.1 结果展示:

3. 数据可视化部分:

3.1(1)根据评论分词出现频率生成词云图:

3.2 结果演示:

3.3(2)生成销售数量和评论数量和日期的关系折线图

3.4 结果演示:

3.5 结论:


数据采集部分:

目标网址:

https://item.jd.com/100066896338.html#none

爬虫思路分析:

1.确定采集目标:爬取“苹果15”的评论包括好评、差评、中评以及不同的评论对应的用户名、设备颜色、设备内存大小、版本号、评论发布时间等字段,共3000条以上的评论数目,如下图所示:

0305a237f0b2423e9dd166203665c212.png

2.查看评论来源:打开网页源代码,按住“Ctrl+F”搜索相应评论,发现并无相关对应信息,即可判断该网站使用了“AJax”动态加载技术。

c76fd19bd54b4101b0bcaf1acb6b5302.png

通过谷歌开发者工具,查看评论来源,发现其来自于API接口,点击负载即可获取其样式(包含其页数、评论数目、评论类型等),这里主要是观察score;根据score值的不同其评论类型也不一样。

98660597bb104b25b318992fa707a136.png

3.确定数据采集技术:根据观察得一个页面具有10条评论,则每一种评论类型至少需要100个页面的评论数目才可达到需求,为了提高采集效率,这里我主要是运用了协程爬虫技术进行数据采集,并通过定义DateFrame数据框将数据放入其中,最后通过pandas库的pancat()方法对数据框进行拼接并保存为csv文件。

import aiohttp
import asyncio
import json
import pandas as pd
import numpy as np
import time

# 使用async关键字修饰一个协程函数main()
async def main(page, score, file_name):
    import requests
    url_str = 'https://api.m.jd.com/'
    url_list = []
    # 将样式复制过来
    params = {
        'appid': 'item-v3',
        'functionId': 'pc_club_productPageComments',
        'client': 'pc',
        'clientVersion': '1.0.0',
        't': '1711815668207',
        'loginType': '3',
        'uuid': '181111935.16981540772521479889794.1698154077.1711813565.1711815580.10',
        'productId': '100066896338',
        'score': score,
        'sortType': 5,
        # 页数从0开始
        'page': page,
        # 每页具有10条评论
        'pageSize': 10,
        'isShadowSku': 0,
        'fold': 1,
    }

    # 目的:为了返回完整的请求网址
    for i in range(page):
        params['page'] = i
        response = requests.get(url_str, params=params)
        url_list.append(response.url)

    # 任务列表
    tasks = []
    for url in url_list:
        print("正在爬取第{}页数据".format(url_list.index(url) + 1))
        # task可视为调用协程函数所返回的对象
        tasks.append(parse_html(url))
    # await用于等待一个Promise对象的解决(即状态变为resolved)后,再继续执行后面的代码。
    # 经过实验得知,使用await asyncio.wait(tasks)时会报错,因为asyncio.wait()返回的是一个元组,包含已完成任务的集合和已取消任务的集合,而不是单独的已完成任务。因此,你应该使用await asyncio.gather(*tasks)来等待所有任务完成并获取它们的结果。
    # results是一个列表,每个元素都是一个DataFrame;每个异步任务的结果会以列表的形式返回,而不会自动合并为一个DataFrame
    results = await asyncio.gather(*tasks)
    all_data = pd.concat(results)
    print(all_data)
    all_data.to_csv(f'{file_name}.csv', encoding='utf-8-sig')

# 解析部分详细代码可查看我往期作品,或者私聊我

if __name__ == '__main__':
    # 开始时间
    time_start = time.time()
    page = int(input("请输入需要爬取的页数:"))
    file_name = input("请输入需要保存的文件名称:")
    score = input("请输入需要爬取的评论类型(1:差评,2:中评,3:好评):")
    # 创建事件循环
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(page, score, file_name))
    # 结束时间
    time_end = time.time()
    print(f"一共用了{time_end-time_start}秒")

结果演示:

控制台输出拼接完后的数据框信息以及程序完成的最终运行时间,如下图所示:

输出数据框内数据:

b4d903da6edc4780a898d79eaf558c0f.png

控制台输出程序完成时间

1ab58f21816c475b92c48c13adaa6ecd.png

通过all_data.to_csv('file_name.csv', encoding='')语句即可将数据框保存为csv文件;如下图所示:

5c755ce1466d45988386f897af55bea1.png

结论:

可看出程序完成后的数据框共有10列的1000条数据且爬取100个页面的时间仅用了26.8秒

数据预处理部分:

1.将分散的文件进行合并:将带有好评、中评、差评的三个csv文件通过读取文件并合并数据框的方式,合并完后的csv文件共3000条数据如下图所示:

5900b1d2f9654adfb76aab62bc0bdfd1.png

2.转变数据类型:通过pands库的to_datetime方法将评论发布时间和购买时间进行数据类型转化,转化结果如下图所示:

import pandas as pd
data_all = []  # 创建一个空列表来存储每个数据框

file_name = ['data1.csv',  'data2.csv',  'data3.csv']

# 合并三个csv文件,统一管理
for file in file_name:
    data = pd.read_csv(file)
    # 将每个数据框添加到列表中
    data_all.append(data)

# 使用 pd.concat() 合并所有数据框
data_all = pd.concat(data_all, ignore_index=True)

# 将指定列数据的时间字符串转化为标准时间
data_all['creationTime'] = pd.to_datetime(data_all['creationTime'])
data_all['referenceTime'] = pd.to_datetime(data_all['referenceTime'])

# 将整合的数据框保存为csv文件
data_all.to_csv('data.csv', encoding='utf-8-sig')

转化前:

52634d455dc44ed3a9c91b0ee1712046.png

 转化后:

c073a11ed20641deb603cc37316b6de4.png

3.观察列表框内相关数据:通过value_counts()方法来查看该列中的元素出现了几次,通过shape()方法即可观察数据框剩余几行数据;通过columns()方法可看出清洗后的数据框的列索引。

c0e5edeacf114d09b45c52b76268f8a6.png

结果展示:

b5cc5bfd8340476f950d8a2c3d629a4d.png

数据可视化部分:

(1)根据评论分词出现频率生成词云图:

1.分词:导入jieba库,将拼接后的data.csv文件进行读取,再对data_all中的content列中的每个文本进行分词操作,使用jieba.lcut函数对文本进行切词。非常值得一提的是:关于中文停用词表可以去我往期作品中直接复制,都是很常用的停用词。

import jieba
from tkinter import _flatten
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib as mpl
import numpy as np
from PIL import Image

# 不是在Jupyter中运行代码,就可能会出现这个问题。可以通过直接在py文件中设置后端use函数来修复这个错误
mpl.use('TkAgg')

# (1)分词
data_all = pd.read_csv('data.csv', encoding='utf-8')
# 对data_all中的content列中的每个文本进行分词操作,使用jieba.lcut函数对文本进行切词
# apply是DataFrame中的一个方法,用于对DataFrame中的某一列(Series)应用指定的函数
data_cut = data_all['content'].apply(jieba.lcut)

2.去除停用词:读取名为stopword.txt的停用词文件,将文件中的停用词加载到stop_list列表中,然后将额外的词语'买'、'手机'、'苹果'添加到stop_list列表中。接着,对经过分词后的文本数据进行停用词过滤,去除stop_list中的词语。

# 读取名为stopword.txt的停用词文件
with open('stopword.txt', encoding='utf-8')as f:
    stop_list = f.read()
# 添加额外通用词
stop_list = stop_list + '买' + '手机' + '苹果'
# 对经过分词后的文本数据data_cut应用lambda函数,该函数会对每个分词后的文本列表进行遍历,只保留不在stop_list中的词语,从而实现停用词过滤
data_after_stop = data_cut.apply(lambda x: [i for i in x if i not in stop_list])

3.统计词频:将经过停用词过滤后的文本数据转换为一个包含所有词语的列表words,然后使用pd.Series(words).value_counts()方法统计每个词语出现的频率,得到词频统计结果。

data_after_stop_list = list(data_after_stop)
words = _flatten(list(data_after_stop_list))
# print(type(words))
# 转化为Serious可使用value_count()方法,统计频率高的词
word_freq = pd.Series(words).value_counts()

4.生成词云图:根据本机内文字字体路径确定生成词云图的文字字体(font_path)、自定义背景图、背景颜色;若未定义文字字体这一步将导致生成图形的文字无法看见,最后通过to_file()方法保存词云图即可。

mask = np.array(Image.open('p11.png'))
# print(mask)
# 创建词云图对象
wc = WordCloud(font_path = 'C:/Windows/Fonts/simhei.ttf' ,mask = mask, background_color='white')
wc.fit_words(word_freq[:80])
plt.imshow(wc)
plt.axis('off')
plt.show()
# 保存生成的词云图
wc.to_file('p13.png')

结果演示:

词云图1:

bd676829a594409698ee1fed47a6c58d.png

80c5a767e23b4a679e5277d63ff28bfa.png

词云图2:

01faf143f38a4c339488eba9a3fd838e.png

60624c337852472fb5ccb3ea68622cfa.png

(2)生成销售数量和评论数量和日期的关系折线图

1.设置绘图参数:字体。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl

mpl.use('TkAgg')

# 设置绘图参数
# 指定了 Matplotlib 使用的字体为宋体(SimSun),即 'simHei'。这样设置可以确保在绘制图表时使用宋体字体显示中文文本,避免中文显示乱码的问题。
plt.rcParams['font.sans-serif'] = 'simHei'
# 设置了 Matplotlib 绘图时坐标轴上的负号显示为正常的减号。在某些情况下,默认设置下负号可能显示不正确,通过将该参数设置为 False,可以确保负号显示正确。
plt.rcParams['axes.unicode_minus'] = False

2.将在数据预处理部分的步骤2转化得到的标准时间‘creationTime’、‘referenceTime’求和并排序赋值给num1、num2。

num1 = data_all['referenceTime'].dt.date.value_counts().sort_index()
num2 = data_all['creationTime'].dt.date.value_counts().sort_index()

# 按列方向拼接两份数据
data = pd.concat([num1, num2], axis=1).fillna(0)

3.使用‘gglot’的绘图风格,使用matplotlib.pyplot的plot方法建立折线图;横坐标为数据data的索引范围,纵坐标为data中名为'referenceTime'以及‘creationTime’的列的数值。

 采用ggplot的绘图风格
plt.style.use('ggplot')
# 销量随日期的变化趋势, 后者为列索引中前者数量对应的内容(即该内容出现了多少次)
plt.plot(range(len(data)), data['referenceTime'])
# 评论数据随日期变化趋势
plt.plot(range(len(data)), data['creationTime'])

4.最后使用matplotlib.pyplot的xticks方法设置x轴刻度标签、标题等。

# plt.xticks() 是 Matplotlib 库中用来设置 x 轴刻度标签的函数
# range(len(data))[::21] 生成一个从 0 到数据长度的序列,间隔为 21,(0,21,42...),用来指定要显示的刻度位置。
# data.index[::21] 是根据数据的索引生成一个新的索引序列,也是步长为 21,(0,21,42...)用来作为刻度标签的内容。
plt.xticks(range(len(data))[::21], data.index[::21], rotation = 45)
plt.legend(['购买数量', '评论数量'])
plt.xlabel('日期')
plt.ylabel('数量')
plt.title('销售数量和评论数量和日期的关系')
plt.show()

结果演示:

810e5d6690e34fb3a310074b815189a2.png

结论:

由图可得2023年10.26日(京东于惊喜红包发放第一阶段)该手机销量呈现爆发式增长乃至11月20日销量发生第二波爆发式增长。

注意:因文章篇幅问题,部分源代码无法展现,如有需要,请在后台私信博主哦~

创作不易,请点个赞哦~

还有更多优秀作品在博主主页~

  • 66
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值