前言
文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。
PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取
http://note.youdao.com/noteshare?id=3054cce4add8a909e784ad934f956cef
第一步:爬取商品排名和详情页链接,需要的字段为:排名、商品名、详情页链接 第二步:爬取商品详情,需要的信息为:
-
店家:这不就是竞争对手吗?分析其爆品情况,保留店家链接,后续可针对性挖掘分析
-
价格:分析爆品价格区间,对商品定价、切分市场有帮助
-
上架时间:新品?爆了多久?
-
星级、评论数、评论标签、所有评论链接:进一步爬取评论内容,来分析爆品的优劣势
-
尺寸、颜色:也是非常有价值的参考数据,但在实际爬取过程中遇到问题,后面会提到
-
图片链接:难道你不想看看商品长啥样吗?
第三步:数据转化为可视化图表,并做分析。
是不是迫不及待想要看过程了,来吧~
如何爬取内衣数据
爬取过程分为三步
1、爬取商品排名和详情页链接
需要爬取的具体字段:排名(Rank),商品名(item_name),商品详情页链接(item_link)、商品图片链接(img_src)
2、在商品详情页爬取更多商品信息
核心事项:
1)构建函数来获取单个商品的详细信息; 2)利用for循环,遍历商品详情页链接列表,来获取每个商品的详细信息
3、爬取评论
核心事项:
1)从上一步的csv文件中,读取Rank , item_name , reviews , reviews_link字段 2)构建函数读取每个商品的所有评论 3)利用for循环,获取所有商品的所有评论 4)存储到数据库和csv文件中
4、爬取size和color数据
和第三步基本一样,代码基本一样,主要在于要确认每页评论的size&color个数。
数据清洗与预处理
1、读取、清洗数据
从csv文件读取100个商品的数据,筛选出所需要的字段,进行数据清洗
-
部分读取的数据,看似是数值,实际是字符,因此需要进行类型转换(如price拆分后,还需要转为float型)
-
需要参与数值计算的NaN,使用平均值进行替换
2、以商家维度处理数据
获取所需的数据:商家的星级、评论数总和、评论数均值、最低价均值、最高价均值、价格均值、商品数量、占比。针对星级、评论数均值、价格均值、商品数量做标准化处理,并计算加权分。
歪果情趣内衣哪家强?
① 不同商家的星级排名
-
平均星级达4.15分,高于平均分的商家超过一半(17/32)
-
Top1的LALAVAVA高达4.9分,紧随其后也有5家达到4.5分。
-
倒数第一N-pearI只有3.2分
让我看看LALAVAVA长什么样。亚马逊上的商品,看上去就是普通泳衣,米国人还是很保守的嘛~
但评分高真的就说明产品好吗?不如来看看评论数吧——
②不同商家的平均评论数排名
-
首先平均评论数只有193条,而且高于平均线的只有不到三成(12/32),想想淘宝动辄上万,我们的人口优势让米国人羡慕呀;
-
再来看星级Top1的LALAVAVA,评论数少得可怜,那么对其商品真实质量就要存疑了;
-
而星级倒数的N-pear I,同样评论数很少,那大概率其商品其实不咋地;
-
反观评论数Top1的Garmol,其星级评价4.4,口碑佳评论也多,看来是不错的商品;
-
紧随其后的几家,其星级分数就低于平均分了
那么,亚马逊的星级评价难道就只受评论数的几颗星比例影响吗?我查阅了网上的一些资料,发现亚马逊评价星级评定的三个重要因素:评论距离现在的时间,评论被买家投票采纳数,评论是否有verified purchase标志(意指真实买家)。此外,评论的字符数,被点击次数等因素也可能会对评论星级有影响。
看来,亚马逊对评论的监控和管理是非常严格而复杂的!当然,最重要的还是看看评论第一名的Garmol长什么样:
比上边的泳衣更点题了,大家说好才是真的好,very sexy!
③不同商家的价格区间排名(按均价)
-
从图上来看,明显ELOVER锁定的是高端市场,定价区间在49刀左右;相反,Goddessvan定价仅0.39刀,还只有一款,猜测可能是亏本冲量,提高商家曝光,抢夺低端市场
-
从均价来看,基本分布在10-20刀间,说明这是情趣内衣市场的主要价格区间;但20-40刀区间居然没有任何商家,可以在这一块深入研究,看能不能找到证据说明该区间是蓝海,有更大的市场潜力
-
而从每个商家的价格区间来看,大多数都是采取多颜色或款式的策略,一方面为用户提供更多选择,另一方面也体现了商家的上新能力;而仅有少数几家采取了单一爆款的策略
最奢华的ELOVER看上去果然比较女神,缩略图都比别家更用心。
那么,到底哪个商家的策略更靠谱,市场份额更大呢?
④商家的商品数量饼图
-
在Top100的商品占比中,Avidlove以28%的巨大优势称霸
-
而其他商家基本都是个位数的占比,没有很明显的优劣势
Avidlove的内衣是酷酷风的,我喜欢。
单一方面毕竟还是很难衡量哪家商家更优秀,不如综合多个指标来分析吧~
⑤不同商家的加权分排名
将星级、平均评论数、商品均价、商品数量进行标准化处理后,因为不好拍定加权的比例,便将4项的归一化结果x10后直接累加得到总分,并制作成堆积图。
而每个商家的4项指标的占比,则侧面反映其自身的优劣势。
-
Avidlove,刚刚的酷酷风内衣,在其他三项中规中矩的情况下,以商品数量优势夺得综合分第一,有种农村包围城市的感觉
-
Garmol,主要依靠口碑(星级、平均评论数)的优势,夺得了第二名
-
ELOVER,主要依靠精准切分高端市场,夺得了第三名
-
N-pearI,没有任何优势,不出意料的光荣垫底
口碑最差的N-pearI,能搜到的商品也最少,不过图很劲爆……就不放出来,太劲爆了~
粗略来看的话,想要排名靠前,口碑一定不能太差,至少要保持在平均水平及以上!
⑥不同商家的星级/价格散点图
x轴为商家的商品均价,y轴为商家的星级,点大小为商品数量,商品数量越大,点越大,点颜色为评论均值,评论均值越大,颜色越深红。
利用价格均值和星级均值,将图切分为四个象限:
①左上象限:实惠好评的商家 ②右上象限:有点贵,但一分钱一分货的商家 ③右下象限:贵,但质量不咋地的商家 ④左下象限:便宜没好货的商家
所以借助这张散点图,挑商家买东西就容易多啦:
-
追求性价比,可选择Avidlove,而且商品多,任君挑选 (图中圆圈最大的浅红色商家);
-
追求高端,可选择ELOVER,它贵有它的道理 (图中最左侧且落在左上象限的商家);
-
追求大众,可选择Garmol,评论数最多,而且好评居多 (图中颜色最红的商家)
顾客可以根据自己的喜好挑选合适的商家,那么作为商家如何改进自己呢?
⑦词频分析
前面在爬取的过程中,同样爬取了评论标签,通过对此进行词频分析,可以发现顾客最关心的依次是:
1.是否合身:size、fit等相关字眼多次出现且排位靠前 2.质量:good quality、well made;soft and comfortable、fabric是对材质的肯定 3.款式:cute、sexy、like the picture你懂的 4.价格:cheaply made勉强算价格吧,但更多是对商品质量的怀疑 5.口碑:highly recommend,评论的还是非常有参考价值的
评论标签的数量较少,进一步对2.4w条评论进行词频分析,并制作成词云:
最直观的,仍然是跟“是否合身”以及质量或款式有关。那么我们就从顾客购买商品的Size&Color继续分析
Size&Color的词频数据存在几点问题:
1、数据量较少,仅有约6000条 2、Size&Color无法较好的区分开,因此一起分析 3、商家的命名规则不同,比如同样是黑色款,有个商家会命名black,而有的可能是style1(所以一些奇怪的数字编号其实是商家的款式编号) 4、有些奇怪的字眼如trim可能是爬虫时爬错了或者导出csv时的格式错乱
可以明显看出:
Size方面:large、medium、small肯定均有涵盖,但另外还有xlarge、xxlarge、xxxlarge,亚马逊主要是欧美顾客,可能体型相对较大,所以商家应该多研发以及备货针对体型较大的顾客的商品。
Color方面:非常直观:Black > red > blue > green > white > purple....所以黑色、红色永远不会错;绿色是出乎我意料的,商家也可以大胆尝试。
Style方面:词频中出现trim、lace字眼,蕾丝最高!!!
完整代码
商品评论
1 # 0、导入模块 2 from bs4 import BeautifulSoup 3 import requests 4 import random 5 import time 6 from multiprocessing import Pool 7 import csv 8 import pymongo 9 ''' 10 python学习交流群:821460695更多学习资料可以加群获取 11 ''' 12 # 0、创建数据库 13 client = pymongo.MongoClient('localhost', 27017) 14 Amazon = client['Amazon'] 15 reviews_info_M = Amazon['reviews_info_M'] 16 17 # 0、反爬措施 18 headers = { 19 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36' 20 } 21 22 # http://cn-proxy.com/ 23 proxy_list = [ 24 'http://117.177.250.151:8081', 25 'http://111.85.219.250:3129', 26 'http://122.70.183.138:8118', 27 ] 28 proxy_ip = random.choice(proxy_list) # 随机获取代理ip 29 proxies = {'http': proxy_ip} 30 31 32 # 1、读取csv中的'Rank','item_name','reviews','reviews_link' 33 csv_file = csv.reader(open('C:/Users/zbd/Desktop/3.csv','r')) 34 reviews_datalst = [] 35 for i in csv_file: 36 reviews_data = { 37 'Rank':i[10], 38 'item_name':i[8], 39 'reviews':i[6], 40 'reviews_link':i[5] 41 } 42 reviews_datalst.append(reviews_data) 43 del reviews_datalst[0] # 删除表头 44 #print(reviews_datalst) 45 reviews_links = list(i['reviews_link'] for i in reviews_datalst) # 将评论详情页链接存储到列表reviews_links 46 47 # 清洗reviews,其中有空值或者“1,234”样式 48 reviews = [] 49 for i in reviews_datalst: 50 if i['reviews']: 51 reviews.append(int(i['reviews'].replace(',',''))) 52 else: 53 reviews.append(0) 54 print(reviews_links) 55 print(reviews) 56 57 # 2、抓取每个商品的评论页链接 58 # 商品 1 59 # 第1页:https://www.amazon.com/Avidlove-Lingerie-Babydoll-Sleepwear-Chemise/product-reviews/B0712188H2/ref=cm_cr_dp_d_show_all_btm?ie=UTF8&reviewerType=all_reviews 60 # 第2页:https://www.amazon.com/Avidlove-Lingerie-Babydoll-Sleepwear-Chemise/product-reviews/B0712188H2/ref=cm_cr_arp_d_paging_btm_next_2?ie=UTF8&reviewerType=all_reviews&pageNumber=2 61 # 第3页:https://www.amazon.com/Avidlove-Lingerie-Babydoll-Sleepwear-Chemise/product-reviews/B0712188H2/ref=cm_cr_getr_d_paging_btm_next_3?ie=UTF8&reviewerType=all_reviews&pageNumber=3 62 # 商品 2 63 # 第1页:https://www.amazon.com/Avidlove-Women-Lingerie-Babydoll-Bodysuit/product-reviews/B077CLFWVN/ref=cm_cr_dp_d_show_all_btm?ie=UTF8&reviewerType=all_reviews' 64 # 第2页:https://www.amazon.com/Avidlove-Women-Lingerie-Babydoll-Bodysuit/product-reviews/B077CLFWVN/ref=cm_cr_arp_d_paging_btm_next_2?ie=UTF8&reviewerType=all_reviews&pageNumber=2 65 # 每页有8个评论,pages = reviews // 8 + 1 66 # 目标格式:https://www.amazon.com/Avidlove-Lingerie-Babydoll-Sleepwear-Chemise/product-reviews/B0712188H2/pageNumber=1 67 url = 'https://www.amazon.com/Avidlove-Lingerie-Babydoll-Sleepwear-Chemise/product-reviews/B0712188H2/ref=cm_cr_dp_d_show_all_btm?ie=UTF8&reviewerType=all_reviews' 68 counts = 0 69 def get_item_reviews(reviews_link,reviews): 70 if reviews_link: 71 pages = reviews // 8 # 每页有8个评论,pages = reviews // 8 ,最后一页不爬取 72 for i in range(1,pages+1): 73 full_url = reviews_link.split('ref=')[0] + '?pageNumber={}'.format(i) 74 #full_url = 'https://www.amazon.com/Avidlove-Lingerie-Babydoll-Sleepwear-Chemise/product-reviews/B0712188H2/?pageNumber=10' 75 wb_data = requests.get(full_url, headers=headers, proxies=proxies) 76 soup = BeautifulSoup(wb_data.text, 'lxml') 77 every_page_reviews_num = len(soup.select('div.a-row.a-spacing-small.review-data > span')) 78 for j in range(every_page_reviews_num): 79 reviews_info ={ 80 'customer_name' : soup.select('div:nth-child(1) > a > div.a-profile-content > span')[j].text, 81 'star' : soup.select('div.a-row>a.a-link-normal > i > span')[j].text.split('out')[0], 82 'review_date' : soup.select('div.a-section.review >div>div> span.a-size-base.a-color-secondary.review-date')[j].text, 83 'review_title' : soup.select('a.a-size-base.a-link-normal.review-title.a-color-base.a-text-bold')[j].text, 84 'review_text' : soup.select('div.a-row.a-spacing-small.review-data > span')[j].text, 85 'item_name' : soup.title.text.split(':')[-1] 86 } 87 yield reviews_info 88 reviews_info_M.insert_one(reviews_info) 89 global counts 90 counts +=1 91 print('第{}条评论'.format(counts),reviews_info) 92 else: 93 pass 94 95 ''' 96 # 这边主要是爬取size和color,因为其数据大量缺失,所以另外爬取 97 # 与上一步的代码基本一样,主要在于要确认每页评论的size&color个数 98 # 写入数据库和csv也需要作相应修改,但方法相同 99 100 def get_item_reviews(reviews_link,reviews): 101 if reviews_link: 102 pages = reviews // 8 # 每页有8个评论,pages = reviews // 8 ,最后一页不爬取,要做一个小于8个评论的判断 103 for i in range(1,pages+1): 104 full_url = reviews_link.split('ref=')[0] + '?pageNumber={}'.format(i) 105 #full_url = 'https://www.amazon.com/Avidlove-Lingerie-Babydoll-Sleepwear-Chemise/product-reviews/B0712188H2/?pageNumber=10' 106 wb_data = requests.get(full_url, headers=headers, proxies=proxies) 107 soup = BeautifulSoup(wb_data.text, 'lxml') 108 every_page_reviews_num = len(soup.select('div.a-row.a-spacing-mini.review-data.review-format-strip > a')) # 每页的size&color个数 109 for j in range(every_page_reviews_num): 110 reviews_info ={ 111 'item_name' : soup.title.text.split(':')[-1], 112 'size_color' : soup.select('div.a-row.a-spacing-mini.review-data.review-format-strip > a')[j].text, 113 } 114 yield reviews_info 115 print(reviews_info) 116 reviews_size_color.insert_one(reviews_info) 117 else: 118 pass 119 ''' 120 121 122 # 3、开始爬取和存储数据 123 all_reviews = [] 124 def get_all_reviews(reviews_links,reviews): 125 for i in range(100): 126 for n in get_item_reviews(reviews_links[i],reviews[i]): 127 all_reviews.append(n) 128 129 get_all_reviews(reviews_links,reviews) 130 #print(all_reviews) 131 132 133 # 4、写入csv 134 headers = ['_id','item_name', 'customer_name', 'star', 'review_date', 'review_title', 'review_text'] 135 with open('C:/Users/zbd/Desktop/4.csv','w',newline='',encoding='utf-8') as f: 136 f_csv = csv.DictWriter(f, headers) 137 f_csv.writeheader() 138 f_csv.writerows(all_reviews) 139 print('写入完毕!')
商品信息
1 # 0、导入模块 2 from bs4 import BeautifulSoup 3 import requests 4 import random 5 import time 6 from multiprocessing import Pool 7 import pymongo 8 ''' 9 python学习交流群:821460695更多学习资料可以加群获取 10 ''' 11 # 0、创建数据库 12 client = pymongo.MongoClient('localhost', 27017) 13 Amazon = client['Amazon'] 14 item_info_M = Amazon['item_info_M'] 15 16 # 0、反爬措施 17 headers = { 18 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36' 19 } 20 # http://cn-proxy.com/ 21 proxy_list = [ 22 'http://117.177.250.151:8081', 23 'http://111.85.219.250:3129', 24 'http://122.70.183.138:8118', 25 ] 26 proxy_ip = random.choice(proxy_list) # 随机获取代理ip 27 proxies = {'http': proxy_ip} 28 29 # 1、爬取商品排名和详情页链接 30 url_page1 = 'https://www.amazon.com/Best-Sellers-Womens-Chemises-Negligees/zgbs/fashion/1044968/ref=zg_bs_pg_1?_encoding=UTF8&pg=1' # 01-50名商品 31 url_page2 = 'https://www.amazon.com/Best-Sellers-Womens-Chemises-Negligees/zgbs/fashion/1044968/ref=zg_bs_pg_2?_encoding=UTF8&pg=2' # 51-100名商品 32 33 item_info = [] # 存储商品详细信息的列表 34 item_links = [] # 存储商品详情页链接的列表 35 def get_item_info(url): 36 wb_data = requests.get(url,headers=headers,proxies=proxies) 37 soup = BeautifulSoup(wb_data.text,'lxml') 38 for i in range(50): 39 data = { 40 'Rank': soup.select('span.zg-badge-text')[i].text.strip('#'), 41 'item_name' : soup.select('#zg-ordered-list > li > span > div > span > a > div')[i].text.strip(), 42 'item_link' : 'https://www.amazon.com' + soup.select('#zg-ordered-list > li > span > div > span > a')[i].get('href'), 43 'img_src' :soup.select('#zg-ordered-list > li> span > div > span > a > span > div > img')[i].get('src') 44 } 45 item_info.append(data) 46 item_links.append(data['item_link']) 47 print('finish!') 48 49 get_item_info(url_page1) 50 get_item_info(url_page2) 51 52 53 54 # 2、在商品详情页爬取更多商品信息 55 #item_url = 'https://www.amazon.com/Avidlove-Lingerie-Babydoll-Sleepwear-Chemise/dp/B0712188H2/ref=zg_bs_1044968_1?_encoding=UTF8&refRID=MYWGH1W2P3HNS58R4WES' 56 def get_item_info_2(item_url,data): 57 wb_data = requests.get(item_url, headers=headers, proxies=proxies) 58 soup = BeautifulSoup(wb_data.text, 'lxml') 59 60 #获取price(需要判断) 61 price = soup.select('#priceblock_ourprice') 62 data['price'] = price[0].text if price else None 63 64 # 获取star和reviews(需要判断) 65 star = soup.select('div>div>span>span>span>a>i>span.a-icon-alt') 66 if star: 67 data['star'] = star[0].text.split(' ')[0] 68 data['reviews'] = soup.select('#reviews-medley-footer > div.a-row.a-spacing-large > a')[0].text.split(' ')[2] 69 data['Read reviews that mention'] = list(i.text.strip('\n').strip() for i in soup.select('span.cr-lighthouse-term')) 70 else: 71 data['star'] = None 72 data['reviews'] = None 73 data['Read reviews that mention'] = None 74 75 data['Date_first_listed_on_Amazon'] = soup.select('#detailBullets_feature_div > ul > li> span > span:nth-child(2)')[-1].text 76 77 # 获取reviews_link(需要判断) 78 reviews_link = soup.select('#reviews-medley-footer > div.a-row.a-spacing-large > a') 79 if reviews_link: 80 data['reviews_link'] = 'https://www.amazon.com' + reviews_link[0].get('href') 81 else: 82 data['reviews_link'] = None 83 84 # 获取store和store_link (需要判断) 85 store = soup.select('#bylineInfo') 86 if store: 87 data['store'] = store[0].text 88 data['store_link'] = 'https://www.amazon.com' + soup.select('#bylineInfo')[0].get('href') 89 else: 90 data['store'] = None 91 data['store_link'] = None 92 93 item_info_M.insert_one(data) # 存入MongoDB数据库 94 print(data) 95 96 97 98 # 3、将商品详情写入csv文件 99 for i in range(100): 100 get_item_info_2(item_links[i],item_info[i]) 101 print('已写入第{}个商品'.format(i+1)) 102 103 import csv 104 headers = ['_id','store', 'price', 'Date_first_listed_on_Amazon', 'item_link', 'reviews_link', 'reviews', 'store_link', 'item_name', 'img_src', 'Rank', 'Read reviews that mention', 'star'] 105 with open('C:/Users/zbd/Desktop/3.csv','w',newline='',encoding='utf-8') as f: 106 f_csv = csv.DictWriter(f,headers) 107 f_csv.writeheader() 108 f_csv.writerows(item_info) 109 110 print('写入完毕!') 111 词云 112 113 114 115 path = 'C:/Users/zbd/Desktop/Amazon/fenci/' 116 117 # 读取文件、分词 118 def get_text(): 119 f = open(path+'reviews.txt','r',encoding = 'utf-8') 120 text = f.read().lower() # 统一改为小写 121 for i in '!@#$%^&*()_¯+-;:`~\'"<>=./?,': # 替换英文符号为空格 122 text = text.replace(i,'') 123 return text.split() # 返回分词结果 124 125 lst_1= get_text() # 分词 126 print('总共有{}个词'.format(len(lst_1))) # 统计总词数 127 128 129 # 去除stop_word(常见词) 130 131 stop_word_text = open(path+'stop_word.txt','r',encoding = 'utf-8') # 读取下载的stop_word表 132 stop_word = stop_word_text.read().split() 133 stop_word_add = ['a','i','im','it鈥檚','i鈥檓','\\u0026','5鈥','reviewdate'] # 可在该列表中继续添加stop_word 134 stop_word_new = stop_word + stop_word_add 135 #print(stop_word_new) 136 lst_2 =list(word for word in lst_1 if word not in stop_word_new) 137 print('去除后总共有{}个词'.format(len(lst_2))) 138 139 # 统计词频 140 counts = {} 141 for i in lst_2: 142 counts[i] = counts.get(i,0) + 1 143 #print(counts) 144 145 word_counts = list(counts.items()) 146 #print(word_counts) 147 148 word_counts.sort(key = lambda x:x[1],reverse = True) # 按词频降序排列 149 150 # 输出结果 151 for i in word_counts[0:50]: 152 print(i) 153 154 155 156 157 # 制作词云 158 from scipy.misc import imread 159 import matplotlib.pyplot as plt 160 import jieba 161 from wordcloud import WordCloud, ImageColorGenerator 162 163 164 stopwords = {} 165 # isCN = 0 # 0:英文分词 1:中文分词 166 path = 'C:/Users/zbd/Desktop/Amazon/fenci/' 167 back_coloring_path = path + 'img.jpg' # 设置背景图片路径 168 text_path = path + 'reviews.txt' # 设置要分析的文本路径 169 stopwords_path = path + 'stop_word.txt' # 停用词词表 170 imgname1 = path + 'WordCloudDefautColors.png' # 保存的图片名字1(只按照背景图片形状) 171 imgname2 = path + 'WordCloudColorsByImg.png' # 保存的图片名字2(颜色按照背景图片颜色布局生成) 172 #font_path = r'./fonts\simkai.ttf' # 为matplotlib设置中文字体路径 ----- 主要是中文时使用 173 174 175 back_coloring = imread(back_coloring_path) # 设置背景图片 ---- back_coloring为3维数组 176 177 wc = WordCloud(#font_path = font_path # 设置字体 178 background_color = 'white', # 设置背景颜色 179 max_words = 3000, # 设置显示的最大词数 180 mask = back_coloring, # 设置背景图片 181 max_font_size = 200, # 设置字体最大值 182 min_font_size = 5, # 设置字体最小值 183 random_state = 42, # 随机有N种配色方案 184 width = 1000 , height = 860 ,margin = 2 # 设置图片默认的大小,但是如果使用背景图片的话 185 # 那么保存的图片大小会按照其大小保存,margin为词语边缘距离 186 ) 187 188 #wc.generate(text) 189 words = {} 190 for i in word_counts: 191 words['{}'.format(i[0])] = i[1] 192 193 wc.generate_from_frequencies(words) 194 # txt_freq例子为 { word1: fre1, word2: fre2, word3: fre3,......, wordn: fren } 195 196 197 plt.figure() 198 199 200 # 以下代码只显示--------形状与背景图片一致,颜色为默认颜色的词云 201 plt.imshow(wc) 202 plt.axis("off") 203 plt.show() # 绘制词云 204 wc.to_file(imgname1) # 保存图片 205 206 207 208 209 # 以下代码显示--------形状与背景图片一致,颜色也与背景图颜色一致的词云 210 image_colors = ImageColorGenerator(back_coloring) # 从背景图片生成颜色值 211 plt.imshow(wc.recolor(color_func=image_colors)) 212 plt.axis("off") 213 plt.show() 214 wc.to_file( imgname2) 215 216 217 218 219 # 显示原图片 220 plt.figure() 221 plt.imshow(back_coloring, cmap=plt.cm.gray) 222 plt.axis("off") 223 plt.show() # 保存图片
数据分析部分
1 import pandas as pd 2 import numpy as np 3 import matplotlib.pyplot as plt 4 import matplotlib.colors 5 ''' 6 python学习交流群:821460695更多学习资料可以加群获取 7 ''' 8 get_ipython().magic('matplotlib inline') 9 10 11 # 0、数据读取 12 13 item_info = pd.read_csv('C:/Users/zbd/Desktop/Amazon/item_info.csv', engine = 'python') 14 reviews_new = pd.read_csv('C:/Users/zbd/Desktop/Amazon/reviews_new.csv', engine = 'python') 15 print(item_info.head()) 16 print(len(item_info)) 17 #print(reviews_new.head()) 18 19 20 21 # 1、清洗数据 22 # 筛选出需要的列 23 item_info_c = item_info[['Rank','item_name','store','price','Date_first_listed_on_Amazon','star','reviews','Read reviews that mention']] 24 25 # 清洗列:price 26 item_info_c['price'] = item_info_c['price'].str.replace('$','') 27 item_info_c['min_price'] = item_info_c['price'].str.split('-').str[0].astype('float') 28 item_info_c['max_price'] = item_info_c['price'].str.split('-').str[-1].astype('float') 29 item_info_c['mean_price'] = (item_info_c['max_price']+item_info_c['min_price'])/2 30 31 # 清洗NaN值 32 def f_na(data,cols): 33 for i in cols: 34 data[i].fillna(data[i].mean(),inplace = True) 35 return data 36 37 item_info_c = f_na(item_info_c,['star','reviews','min_price','max_price','mean_price']) 38 item_info_c.head(5) 39 40 41 42 43 # 2、以商家维度处理数据 44 a = item_info_c.groupby('store')['star'].mean().sort_values(ascending=False) # 商家星级均值 45 b = item_info_c.groupby('store')['reviews'].agg({'reviews_sum':np.sum,'reviews_mean':np.mean}) # 商家评论数总和、均值 46 c = item_info_c.groupby('store')['min_price'].mean() # 商家最低价均值 47 d = item_info_c.groupby('store')['max_price'].mean() # 商家最高价均值 48 e = item_info_c.groupby('store')['mean_price'].mean() # 商家价格均值 49 e.name = 'price_mean' 50 f = item_info_c.groupby('store')['star'].count() # 商家商品数量 51 f.name = 'item_num' 52 #print(a,b,c,d,e,f) 53 54 df = pd.concat([a,b,e,f],axis=1) # 商家商品数量百分比 55 df['per'] = df['item_num']/100 56 df['per%'] = df['per'].apply(lambda x: '%.2f%%' % (x*100)) 57 58 # 标准化处理 59 def data_nor(df, *cols): 60 for col in cols: 61 colname = col + '_nor' 62 df[colname] = (df[col]-df[col].min())/(df[col].max()-df[col].min()) * 10 63 return df 64 # 创建函数,结果返回标准化取值,新列列名 65 66 df_re = data_nor(df, 'star','reviews_mean','price_mean','item_num') 67 print(df_re.head(5)) 68 69 70 71 72 # 3、绘制图表 73 74 fig,axes = plt.subplots(4,1,figsize = (10,15)) 75 plt.subplots_adjust(wspace =0, hspace =0.5) 76 77 # 不同商家的星级排名 78 df_star = df['star'].sort_values(ascending = False) 79 df_star.plot(kind = 'bar',color = 'yellow',grid = True,alpha = 0.5,ax =axes[0],width =0.7, 80 ylim = [3,5],title = '不同商家的星级排名') 81 axes[0].axhline(df_star.mean(),label = '平均星级%.2f分' %df_star.mean() ,color = 'r' ,linestyle = '--',) 82 axes[0].legend(loc = 1) 83 84 # 不同商家的平均评论数排名 85 df_reviews_mean = df['reviews_mean'].sort_values(ascending = False) 86 df_reviews_mean.plot(kind = 'bar',color = 'blue',grid = True,alpha = 0.5,ax =axes[1],width =0.7, 87 title = '不同商家的平均评论数排名') 88 axes[1].axhline(df_reviews_mean.mean(),label = '平均评论数%i条' %df_reviews_mean.mean() ,color = 'r' ,linestyle = '--',) 89 axes[1].legend(loc = 1) 90 91 # 不同商家的价格区间(按均价) 92 avg_price = (d-c)/2 93 avg_price.name = 'avg_price' 94 max_price = avg_price.copy() 95 max_price.name = 'max_price' 96 97 df_price = pd.concat([c,avg_price,max_price,df_re['price_mean']],axis=1) 98 df_price = df_price.sort_values(['price_mean'],ascending = False) 99 df_price.drop(['price_mean'],axis =1,inplace = True) 100 df_price.plot(kind = 'bar',grid = True,alpha = 0.5 , ax =axes[2],width =0.7,stacked = True, 101 color= ['white','red','blue'],ylim = [0,55],title = '不同商家的价格区间') 102 103 # 不同商家的加权分排名 104 df_nor = pd.concat([df_re['star_nor'],df_re['reviews_mean_nor'],df_re['price_mean_nor'],df_re['item_num_nor']],axis =1) 105 df_nor['nor_total'] = df_re['star_nor'] + df_re['reviews_mean_nor'] + df_re['price_mean_nor'] + df_re['item_num_nor'] 106 df_nor = df_nor.sort_values(['nor_total'],ascending = False) 107 df_nor.drop(['nor_total'],axis = 1,inplace = True) 108 df_nor.plot(kind = 'bar',grid = True,alpha = 0.5 , ax =axes[3],width =0.7,stacked = True, 109 title = '不同商家的加权分排名') 110 111 112 113 114 # 商家数量饼图 115 colors = ['aliceblue','antiquewhite','beige','bisque','blanchedalmond','blue','blueviolet','brown','burlywood', 116 'cadetblue','chartreuse','chocolate','coral','cornflowerblue','cornsilk','crimson','cyan','darkblue','darkcyan','darkgoldenrod', 117 'darkgreen','darkkhaki','darkviolet','deeppink','deepskyblue','dimgray','dodgerblue','firebrick','floralwhite','forestgreen', 118 'gainsboro','ghostwhite','gold','goldenrod'] 119 120 df_per = df_re['item_num'] 121 fig,axes = plt.subplots(1,1,figsize = (8,8)) 122 plt.axis('equal') #保证长宽相等 123 plt.pie(df_per , 124 labels = df_per.index , 125 autopct = '%.2f%%', 126 pctdistance = 1.05 , 127 #shadow = True , 128 startangle = 0 , 129 radius = 1.5 , 130 colors = colors, 131 frame = False 132 ) 133 134 135 136 # 不同商家的星级/价格散点图 137 plt.figure(figsize=(13,8)) 138 x = df_re['price_mean'] # x轴为均价 139 y = df_re['star'] # y轴为星级 140 s = df_re['item_num']*100 # 点大小为商品数量,商品数量越大,点越大 141 c = df_re['reviews_mean']*10 # 点颜色为评论均值,评论均值越大,颜色越深红 142 plt.scatter(x,y,marker='.',cmap='Reds',alpha=0.8, 143 s = s,c = c) 144 plt.grid() 145 plt.title('不同商家的星级/价格散点图') 146 plt.xlim([0,50]) 147 plt.ylim([3,5]) 148 plt.xlabel('price') 149 plt.ylabel('star') 150 151 # 绘制平均线、图例 152 p_mean = df_re['price_mean'].mean() 153 s_mean = df_re['star'].mean() 154 plt.axvline(p_mean,label = '平均价格%.2f$' %p_mean ,color = 'r' ,linestyle = '--',) 155 plt.axhline(s_mean,label = '平均星级%.2f' %s_mean ,color = 'g' ,linestyle = '-.') 156 plt.axvspan(p_mean, 50, ymin= (s_mean-3)/(5-3), ymax=1,alpha = 0.1,color = 'g') 157 plt.axhspan(0, s_mean, xmin= 0 , xmax=p_mean/50,alpha = 0.1,color = 'grey') 158 plt.legend(loc = 2) 159 160 # 添加商家标签 161 for x,y,name in zip(df_re['price_mean'],df_re['star'],df_re.index): 162 plt.annotate(name, xy=(x,y),xytext = (0, -5), textcoords = 'offset points',ha = 'center', va = 'top',fontsize = 9) 163 164 165 166 167 # 清洗列:Read reviews that mention 168 df_rrtm = item_info_c['Read reviews that mention'].fillna('缺失数据',inplace =False) 169 df_rrtm = df_rrtm.str.strip('[') 170 df_rrtm = df_rrtm.str.rstrip(']') 171 df_rrtm = df_rrtm.str.replace('\'','') 172 173 reviews_labels = [] 174 for i in df_rrtm: 175 reviews_labels = reviews_labels+i.split(',') 176 #print(reviews_labels) 177 178 179 labels = [] 180 for j in reviews_labels: 181 if j != '缺失数据': 182 labels.append(j) 183 #print(labels) 184 185 186 187 # 统计标签词频 188 counts = {} 189 for i in labels: 190 counts[i] = counts.get(i,0) + 1 191 #print(counts) 192 193 label_counts = list(counts.items()) 194 #print(word_counts) 195 196 label_counts.sort(key = lambda x:x[1],reverse = True) # 按词频降序排列 197 198 print('总共%i个评论标签,Top20如下:'%len(label_counts)) 199 print('-----------------------------') 200 # 输出结果 201 for i in label_counts[:20]: 202 print(i)