一、数据获取
使用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()
四、说明
代码仅提供主要部分,许多功能都可以优化改进,个人水平有限,仅供参考,勿喷谢谢
遇到问题可以多百度!