引言
你是否曾经遇到过要给女朋友、父母、好朋友送礼物却不知道买什么的情况?小编作为一个直男,每次都在给朋友选礼物的事情上费劲脑筋,实在是不知道买什么东西好。但事情总是要解决,小编萌生了一个想法,在某购物网站搜索关键字,然后将搜索结果进行词频分析,这样不就知道有什么东西是大家买的比较多的了么?说干咱就干。
需求分析
通过京东购物网站搜索关键字,将搜索结果中的产品名称进行保存,同时对产品名称进行词频统计,生成可供参考的词云图。
所用知识点
爬虫:requests库(简单的项目,使用requests更方便)
分词:jieba库
词云:pyecharts库
保存文件:csv库
页面解析:BeautifulSoup
目标网站分析
打开京东网站,输入关键字,本例中使用“情人节”,点击搜索。可以看到搜索结果页面如下图所示。除去广告,我们的定位的目标为红色框线内的产品信息。
使用开发者工具,定位页面中的产品,可以看到所有产品都存放在class=‘gl-item’的li标签中。可以通过select(".gl-item")确定所有页面中的产品集合。
确定产品后,逐步确定price(产品价格)、title(商品名称)、product_detail_link(商品详情链接)、img_link(图片链接)、评价数量、shop_name(店铺名称)、shop_link(店铺链接)。实际中我们只用到了title这个属性,但是出于习惯,将能用到的内容全部都提取出来,方便以后使用。标签都比较好寻找,就不单列方法,下面是全部元素的定位代码。
r = requests.get(url, params=params, )
r_content = (r.content.decode("utf-8"))
content = BeautifulSoup(r_content, 'lxml')
product = content.select(".gl-item")
for p in product:
product_info = {}
product_info['number'] = num
num += 1
try:
# 价格
product_info["price"] = p.select(".p-price i")[0].get_text()
# 商品名称
product_info["title"] = p.select('.p-name-type-2 a')[0].attrs['title'].strip(" ")
# 商品链接
product_info['product_detail_link'] = p.select('.p-img a')[0].attrs['href'].strip('/')
# 图片链接
product_info['img_link'] = p.select('.p-img a img')[0].attrs['source-data-lazy-img'].strip('/')
# 评价数量
product_info["评价数量"] = p.select('.p-commit a')[0].get_text()
# 商家信息
shop = p.select(".p-shop a")
if len(shop) == 0:
shop_name = ""
shop_link = ""
else:
# 商铺名称
shop_name = shop[0].get_text()
# 商铺链接
shop_link = shop[0].attrs['href']
product_info['shop_name'] = shop_name
product_info['shop_link'] = shop_link
在提完当前页之后,我们肯定不能满足只爬取一页的内容,如果只要一页的内容我猜不用爬虫应该更简单。下一步就是不断提取下一页的链接,并不断访问提取数据。
在搜索结果中点击下一页,观察url变化。(比较过程略)
通过观察比较,我们可以得到一个规律。在url中必须传的参数有keyword(搜索关键字)、enc(编码)、s(内容数量)、page(当前页)。其中只有page是变化参数,其他都是固定参数。所以我们可以不断的构建page参数,来访问不同的页面。代码如下:
url = "https://search.jd.com/Search"
params = {
"keyword": keyword,
"enc": "utf-8",
"s": 50,
}
for i in range(1, 200, 2):
params['page'] = i
r = requests.get(url, params=params, )
通过不断的构建url地址,我们可以访问全部的搜索结果。
保存
通过上面的提取内容代码,我们可以将所有需要的信息放在一个list中,每个list元素是一个product_info字典。通过csv库,将得到的内容保存到csv文件中。
def save_info(product_list,file):
fieldnames = ['number','price','title','product_detail_link','img_link',"评价数量",'shop_name','shop_link']
with open(file,'a',newline="") as csvfile:
writer = csv.DictWriter(csvfile,fieldnames=fieldnames)
writer.writeheader()
for product_info in product_list:
#写入时需要注意,有些商品名称包含“✅”或“❤”特殊字符,是无法写入的,要做处理
try:
writer.writerow(product_info)
except:
print(str(product_info) + "写入错误")
这里需要注意的一点是,因为有些产品名称中包含“✅”,“❤”这样的特殊字符,是无法写入到csv中的,需要对写入代码做异常判断。(偷偷的告诉你,这个错误还真浪费了小编一些时间,一直都是写入报错,后来才找到是特殊字符的锅)
分词
保存文件之后,我们通过另一个函数读取csv中的title字段(这里也可以直接使用爬虫代码中提取的数据,小编只是习惯将数据保存),通过jieba库,对数据进行中文分词。jieba库可以将一个中文字符串进行中文分词,是一个很好用的中文分词库(具体使用方法后续会发笔记)。首先将所有title提取出来,并组合成一个字符串,通过jieba.cut对该字符串进行分词。具体代码如下:
seg_list = jieba.cut(data_string, cut_all=False)
生成词云
在得到分词结果之后,我们要对结果进行加工,得到一个{词:出现次数}的字典,当然为了去除一些无用的词和低频的词,我们还需要一个筛选。筛选代码略。可以通过源码查看。
得到{词:出现次数}的字典之后,我们就可以使用pyecharts库中的WordCloud进行词云生成。具体代码如下:
wordcloud = WordCloud(width=1300, height=620)
for k,v in seg_count_bigthan100.items():
word.append(k)
count.append(v)
wordcloud.add("词云图", word, count, word_size_range=[20, 100],shape="diamond")
wordcloud.render()
结果
下面是小编搜索几个关键字之后的词云结果。
情人节:
七夕:
源码:
链接:https://pan.baidu.com/s/1vbmgwDo5-lfziOTcInwKvg 密码:7km1