一、数据获取
使用PyCharm(引用requests库、lxml库、json库、time库、openpyxl库和pymysql库)爬取京东网页相关数据(品牌、标题、价格、店铺等)
数据展示(片段):
京东网页有反爬措施,需要自己在网页登录后,获取cookie,加到请求的header中(必要时引入time库,设置爬取睡眠时间降低封号概率)
爬取代码(片段):
###获取每一页的商品数据
def getlist(url,brand):
global count #定义一个全局变量,主要是为了确定写入第几行
# url="https://search.jd.com/search?keyword=笔记本&wq=笔记本&ev=exbrand_联想%5E&page=9&s=241&click=1"
res = requests.get(url,headers=headers)
res.encoding = 'utf-8'
# text = (res.text).replace("")
text = res.text
selector = etree.HTML(text)
list = selector.xpath('//*[@id="J_goodsList"]/ul/li')#获取数据所在
for i in list:
title = i.xpath('.//div[@class="p-name p-name-type-2"]/a/em/text()')[0].strip()#商品名称
price = i.xpath('.//div[@class="p-price"]/strong/i/text()')[0]#商品价格
shop = i.xpath('.//div[@class="p-shop"]/span/a/text()')[0] #获取店铺名称
#获取评论数的id值
# product_id = i.xpath('.//[@class="p-commit"]/strong/a/@id')[0].replace("J_comment_","")
# comment_count = commentcount(product_id)
# print("目前条数="+str(count))
爬取完后直接存入数据库:
# 实现将数据写入到数据库中吗,提前将库和表创建好,创建表结构如下:
"""CREATE TABLE jd.shuju(
id INT PRIMARY KEY AUTO_INCREMENT,
brand VARCHAR(100) CHARACTER SET utf8,
title VARCHAR(100) CHARACTER SET utf8,
price VARCHAR(100) CHARACTER SET utf8,
shop VARCHAR(100) CHARACTER SET utf8,
comment_count VARCHAR(100) CHARACTER SET utf8);
"""
conn = pymysql.connect(
host='127.0.0.1',
user='root',
passwd='',
port=3306,
db='jd',
charset='utf8',
use_unicode=True
)
# print("连接成功")
cursor = conn.cursor() # 执行完毕返回的结果集默认以元组显示
# 向sql中插入数据
try:
sql = f"insert ignore into shuju111(brand,title,price,shop) values('{brand}','{title}','{price}','{shop}')"
cursor.execute(sql) # 执行SQL语句
# print("插入完一条语句")
cursor.close() # 关闭光标对象
conn.commit() # 提交
conn.close() # 关闭数据库
except:
print("跳过1次插入")
continue
#向表中插入数据
outws.cell(row=count, column=1, value=str(count - 1)) # 从第一行开始
outws.cell(row=count, column=2, value=str(brand))
outws.cell(row=count, column=3, value=str(title))
outws.cell(row=count, column=4, value=str(price))
outws.cell(row=count, column=5, value=str(shop))
# outws.cell(row=count, column=6, value=str(CommentCount))
count = count + 1 # 自动跳入下一行
二、数据处理
对所爬取数据中无关数据进行清洗(符号的替换)
代码部分:
# 调用函数模拟请求获取评论数
def commentcount(product_id):
url = "https://club.jd.com/comment/productCommentSummaries.action?referenceIds="+str(product_id)+"&callback=jQuery8827474&_=1615298058081"
res = requests.get(url, headers=headers)
res.encoding = 'utf-8' #字符转换
text = (res.text).replace("jQuery8827474(","").replace(");","") #替换掉前面出现的jQuery5597865
text = json.loads(text) #将字符串转换为json格式
comment_count = text['CommentsCount'][0]['CommentCountStr']
comment_count = comment_count.replace("+", "")
#对万进行操作,数据清洗
if "万" in comment_count:
comment_count = comment_count.replace("万","")
comment_count = str(int(comment_count)*10000)
return comment_count
三、数据可视化
调用数据库数据利用matplotlib.pyplot进行图像绘制(主要根据品牌、店铺、平均价格进行相关数据可视化)
品牌—数量可视化效果:
代码部分:
#画品牌和数量的图表
plt.title('品牌-数量')
plt.xlabel('品牌')
plt.ylabel('品牌数量')
x = ['联想(lenovo)', 'Apple', '宏碁(acer)', '华为(HUAWEI)', 'ThinkPad', '戴尔(DELL)', '小米(MI)']
y = [count_pp[item] for item in x]
plt.bar(x, y)
plt.show()
店铺—数量可视化效果:
代码部分:
#店铺及数量表
count_dp = {'联想京东自营旗舰店':0,'联想京东自营官方旗舰店':0,'联想商用丽邦专卖店':0,
'联想商用融合汇通专卖店':0,'联想扬天京东自营授权旗舰店':0}
sql1 = "select * from shuju where brand = '联想(lenovo)' and id<24"#分析前二十个店铺
cursor.execute(sql1)
results1 = cursor.fetchall() # 以元组的形式返回
for row in results1:
count_dp[row['shop']] += 1
plt.title('店铺-数量')
plt.xlabel('店铺')#横坐标代表含义
plt.ylabel('店铺数量')
x = ['联想京东自营旗舰店','联想京东自营官方旗舰店','联想商用丽邦专卖店',
'联想商用融合汇通专卖店','联想扬天京东自营授权旗舰店']
y = [count_dp[item] for item in x]
plt.bar(x, y)
plt.show()
品牌—价格可视化效果:
代码部分:
#根据平均价格分析
plt.title('品牌-价格')
plt.xlabel('品牌')
plt.ylabel('品牌价格')
x = ['联想(lenovo)', 'Apple', '宏碁(acer)', '华为(HUAWEI)',
'ThinkPad', '戴尔(DELL)', '小米(MI)']
y = [price_total[item]/count_pp[item] for item in x]
plt.bar(x, y)
plt.show()
品牌占比例可视化效果:
代码部分:
#饼图分析品牌占比
explode = (0,0,0,0.1,0,0,0,0)
candidate = [key for key in count_pp] #拿取品牌的键名
votes = [value for value in count_pp.values()] #拿取品牌的键值
plt.figure(figsize=(10, 10), dpi=100)
plt.pie(votes, labels=candidate, explode=explode, autopct="%1.2f%%", shadow=False, startangle=90,
textprops={'fontsize':15},labeldistance=1.05)
#labels饼图外侧显示的说明文字,explode为突出某个值,autopct设置百分比小数位,shadow表示阴影,
# startangle起始绘制角度,默认图是从x轴正方向逆时针画起,设定=90则从y轴正方向画起;
# labeldistance:label标记的绘制位置,相对于半径的比例,默认值为1.1, 如<1则绘制在饼图内侧;
plt.legend(loc='upper right',fontsize=6) #设置图例位置和大小
plt.title("各品牌占比")
plt.axis('equal')
plt.show()
店铺占比例可视化效果:
代码部分:
#画环形饼图
candidate1 = [key for key in count_dp] #拿取品牌的键名
votes1 = [value for value in count_dp.values()] #拿取品牌的键值
plt.figure(figsize=(10, 10), dpi=100)
explode1=[0,0,0,0,0]
plt.pie(votes1, labels=candidate1, explode=explode1, autopct="%1.2f%%", shadow=False, startangle=90,
textprops={'fontsize':15},pctdistance=0.85,labeldistance=1.05)
plt.pie([1],radius=0.7,colors='w') #在内部画一个白色的圆
plt.legend(loc='upper left',fontsize=6)
plt.title("各店铺占比")
plt.axis('equal')
plt.show()
四、说明
代码仅提供主要部分,许多功能都可以优化改进,个人水平有限,仅供参考,勿喷谢谢
遇到问题可以多百度!
本文转载自: https://blog.csdn.net/m0_50902656/article/details/122075031
版权归原作者 m0_50902656 所有, 如有侵权,请联系我们删除。
版权归原作者 m0_50902656 所有, 如有侵权,请联系我们删除。