耗时三天,终于写完了一个爬虫,现在就将它记录下来。
通过爬虫去爬取京东的用户评价,通过分析爬取的数据能够得到哪一种颜色的内衣比较受小姐姐们的喜爱、以及中国小姐姐们的真实罩杯。
网页分析
首先打开京东首页,并搜索【内衣女】,将会出现商品信息。
URL地址如下:
https://search.jd.com/Search?keyword=内衣女&enc=utf-8&wq=内衣女&pvid=4d7426e03119404f98c55ecb20de787e
价格、标题、商品ID
在这个页面中我们需要获取到每一件商品的价格、标题以及商品的ID。对于价格和标题,我相信大家都不会有任何的疑惑。因为接下来,我们需要获取到评论数、评价的数据,所以我们需要进入详情页,例如,我们拿上面图片的四件产品为例,点击进去之后,你就会发现我们进入了详情页。
前四件商品的详情页URL地址如下所示:
https://item.jd.com/100014910630.html
https://item.jd.com/56716346225.html
https://item.jd.com/100003425463.html
https://item.jd.com/100005850583.html
看到这四个URL链接之后,想必你应该明白变化的数据就是这串数字而已,因此我们可以在网页源码中查找是否存在这类数据。
打开开发者工具,在页面中搜索上面任意一串数字,例如,搜索:100014910630
从上图,你会看到数据是在网页源码中的,因此为我们接下来提取数据,提供了不少的便利。
提取价格、标题、商品ID这三种数据,我使用Xpath来提取。
核心代码,如下所示:
def get_info(self, html):
titles = []
prices = []
comment_counts = []
good_counts = []
selector = etree.HTML(html)
lis = selector.xpath('//*[@id="J_goodsList"]/ul/li')
for li in lis:
title = li.xpath('.//div[@class="p-name p-name-type-2"]/a/em/text()')[0].replace('\t\n', '').replace('\n', '')
titles.append(title)
price = float(li.xpath('.//div[@class="p-price"]/strong/i/text()')[0])
prices.append(price)
product_id = li.xpath('.//div[@class="p-commit"]/strong/a/@id')[0].replace('J_comment_', '')
评价数与好评数
在这里我们就需要思考一个问题了,评价数和好评数这类数据是怎么样生成的?试想一下,如果今天有10000人购买内衣并评价,那程序员是不是要去修改网页源代码?
如果你是这样认为的话,那你就太小看京东的程序员了吧。
因此,我判断肯定不是上面的那种情况,不是通过Ajax异步加载就是通过js渲染。
功夫不负有心人,在详情页中刷新网页,并查看数据加载过程,终于让我给找到了,它是通过js进行渲染出来的数据。
如下图所示:
好评数与评论数在这里都出现了。
这段数据还是很迷惑人的,咋一看是不是很像json数据,只是很像而已,你如果仔细看的话其实并不是,需要我们做简单的处理。
删除前面的jQuery7484346(
以及后面的);
这两处的字符串,就可以将上面的数据转化为json格式的数据了。
接下来,我们点击headers,查看它的URL信息,如下图所示:
从上图你有没有发现很有意思的事情,标记的数据是不是很熟悉,对的,标记的数据正是我们的商品ID,经过测试发现,其他参数均不需要改变,只需要将商品的ID替换掉即可,这样我们就可以获取到所有商品的评论数与好评数了。
核心代码如下所示:
def get_comment_count(self, id):
url = f'https://club.jd.com/comment/productCommentSummaries.action?referenceIds={id}&callback=jQuery5250105&_=1615718915139'
time.sleep(0.3)
html = requests.get(url, headers=self.headers).content.decode('gbk')
text = html.replace('jQuery5250105(', '').replace(');', '')
json_text = json.loads(text)
comment_count = jsonpath.jsonpath(json_text, '$..CommentCountStr')[0].replace('+', '')
good_count = jsonpath.jsonpath(json_text, '$..GoodCountStr')[0].replace('+', '')
if '万' in good_count:
good_count = int(good_count.replace('万', '')) * 10000
if '万' in comment_count:
comment_count = int(comment_count.replace('万', '')) * 10000
return comment_count, good_count
当然,在这里我们需要做简单的处理,比如说,数据中含有万字
,我们需要对万字进行删除,并乘以10000即可。
处理json数据的时候,我依然还是采用jsonpath这个模块。这样总比获取字典的值要容易很多吧。
接下来通过上面的get_info()
函数,来调用get_comment_count()
函数,从而将评论数和好评数获取下来。
具体代码,如下所示:
def get_info(self, html):
titles = []
prices = []
comment_counts = []
good_counts = []
selector = etree.HTML(html)
lis = selector.xpath('//*[@id="J_goodsList"]/ul/li')
for li in lis:
title = li.xpath('.//div[@class="p-name p-name-type-2"]/a/em/text()')[0].replace('\t\n', '').replace('\n', '')
titles.append(title)
price = float(li.xpath('.//div[@class="p-price"]/strong/i/text()')[0])
prices.append(price)
product_id = li.xpath('.//div[@class="p-commit"]/strong/a/@id')[0].replace('J_comment_', '')
comment_count = int(self.get_comment_count(product_id)[0])
comment_counts.append(comment_count)
good_count = int(self.get_comment_count(product_id)[1])
good_counts.append(good_count)
result = zip(titles, prices, comment_counts, good_counts)
return result
保存数据
一般来说,我是将数据都保存在MySQL数据库中,这样方便我导进导出。这里需要用到pymysql这个模块,需要安装才能使用,安装方法如下:
pip install pymysql
我在数据库中创建了数据表underware5,里面包含了几个字段:title、price、commentcount、goodcount。commentcount代表评论数,而goodcount则代码好评数。
内衣畅销量展示
一般来说,评论数越多的商品,证明销量就越高。因此我做了简单的图形,对好评数和评论数进行简单的排序,如下图所示:
排名比较靠前的是猫人、欧阳娜娜、南极人和都市丽人等。这里我选取了前十名作为参考。
内衣价格排行
我从获取到的价格数据中,取出前十名的内衣价格并绘制简单的图形展示出来,如下图所示:
价格最高的内衣是【大绒鹅维多利亚】,这款内衣的价格居然高达558元。其他的内衣品牌价格都是维持在360到390之间。
看来这款内衣怕是有什么强大的过人之处吧。
分析欧阳娜娜
欧阳娜娜这个品牌我简单的看了一下,不论是在淘宝还是在京东的销量都是蛮高的。因此就单独分析一下欧阳娜娜这个品牌,看看小姐姐们的评论、大小、评分以及喜欢的颜色。
因为评论存在详情页中,因此我们还是要具体分析详情页的数据。
同样,我们需要思考一个问题,假如今天有1000人评论,那么程序员是不是要手动的把评论嵌入到网页源码中?
这不是废话吗?
怎么可能。
因此,在这里我同样判断这很有可能是通过js进行渲染的数据。将详情页进行刷新,明确目标之后,很快我便找到了数据所在。如下图所示:
在这里并不是简单的刷新就可以了,需要将网页不断的下滑,直到评论出现,该数据才能够加载出来。
同样的,我们可以点击headers,查看该数据的URL链接,如下所示:
第一个标记指的就是商品ID,第二个标记指的就是处于评论区的第几页。
因此,相同的商品中,变化的数据就只有page。
在这里京东其实也是有反爬措施的,我们不可能把20万的数据都爬取下来,只能爬到第99页就结束了,但是我爬了两个商家的欧阳娜娜的数据,爬下2000条左右的数据,做数据分析。
小姐姐的评论
为什么欧阳娜娜的销量那么高呢?这就不得不看他们到底评论了些什么内容了。
从上面的词云图中,不难发现这款内衣不仅面料好、质量好,而且穿着舒适,难怪那么多人买了。
小姐姐的真实Size
在这里我就分析了个寂寞。
原来欧阳娜娜的内衣哪有什么罩杯啊,适合的是A~C杯的小姐姐们穿,听说这款内衣弹性不错,所有的内衣都是均码。
分析都市丽人
既然上面的全是均码,我想很多老司机们就会死心,所以我就把都市丽人的数据抓取下来,满足你们。
小姐姐的评论
很显然,都市丽人与欧阳娜娜的评论是差不多的,因此这两款内衣都是相当不错的。
小姐姐喜欢的颜色
通过上面的两张图片,很明显最多人买的是藕粉色,其次是淡银灰。
小姐姐的真实Size
来来,老司机们快上车。
你们最想看的来了,看看有多少人连上面的代码都不看直接下拉到最后看结果的。
我不知道你们看到了什么,反正我就是看了个寂寞。除了A、B、C是罩杯的意思,其他全都不知道了。
经过专业人士的指导,我明白了,原来前面的数字代表的是胸的下围,只是不同地方对码数描述不同。
看来小姐姐们的胸围都集中在32B和36B是比较多的呀!
听说都市丽人这个品牌,学生党居多,所有看到罩杯的分布,相信你们懂的都懂。
最后
没有什么事情是可以一蹴而就的,生活如此,学习亦是如此!
因此,哪里会有什么三天速成,七天速成的说法呢?
唯有坚持,方能成功!
啃书君说:
文章的每一个字都是我用心敲出来的,只希望对得起每一位关注我的人。在文章末尾点【赞】与【在看】,让我知道,你们也在为自己的学习拼搏和努力。
路漫漫其修远兮,吾将上下而求索。
我是啃书君,一个专注于学习的人,你懂的越多,你不懂的越多。更多精彩内容,我们下期再见!