充氣娃娃什么感覺?


ps:本文參考“裸睡的豬”公眾號。

 

 本文中所用的到第三方庫有:

requests   jieba   numpy    Pillow    wordcloud    matplotlib

前言:

基於很多人沒有體驗過充氣娃娃是什么感覺,但是又很好奇,所以希望通過爬蟲+數據分析的方式直觀而真實的告訴大家(下圖為成品圖)

 

 

一、技術方案

1、分析狗東評論數據的請求url

2、使用requests庫來抓取評論內容

3、使用詞雲做數據展示

二、技術實現

1、分析並獲取商品評論的接口

第一步:打開狗東的商品頁,搜索你想研究的商品。我們這里直接搜索“充氣娃娃”,然后進入第一個店鋪。

 

第二步:我們在頁面中鼠標右鍵選擇檢查(或F12)調出瀏覽器的調試窗口。

 

 

第三步:調出瀏覽器后點擊評論按鈕使其加載數據,然后我們點擊network查看數據。

 

 

 

 第四部:點擊Headers,獲取評論的接口

 

 

經過上面的步驟,我們就輕松的獲取到了評論的請求接口。

 

2、爬取數據

拿到評論數據接口url之后,我們就可以開始寫代碼抓取數據了。一般我們會先嘗試抓取一條數據,成功之后,我們再去分析如何實現大量抓取。

import requests


def spider_comment():
    """爬取狗東評論數據"""
    kv = {'Referer': 'https://item.jd.com/1070129528.html',
          'Sec-Fetch-Mode': 'no-cors',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}

    url = 'https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv9087&productId=1070129528&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'
    try:
        result = requests.get(url, headers=kv)
        result.raise_for_status()  # 返回狀態碼。如果返回4XX或者5XX直接執行except
        print(result.text)
    except Exception as e:
        print(e)

if __name__ == '__main__':
    spider_comment()

獲取到如圖數據:

 

 3、數據提取

我們對爬取的數據分析發現,此數據為jsonp跨域請求返回的json結果,所以我們只要把前面的fetchJSON_comment98vv9087(和最后的)去掉就拿到json數據了。

將json數據復制到json格式化工具中或者在Chrome瀏覽器調試窗口點擊Preview也可以看到,json數據中有一個key為comments的值便是我們想要的評論數據。

我們再對comments值進行分析發現是一個有多條數據的列表,而列表里的每一項就是每個評論對象,包含了評論的內容,時間,id,評價來源等等信息,而其中的content字段便是我們在頁面看到的用戶評價內容。

 

 

 

import json

import requests


def spider_comment():
    """爬取狗東評論數據"""
    kv = {'Referer': 'https://item.jd.com/1070129528.html',
          'Sec-Fetch-Mode': 'no-cors',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}

    url = 'https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv9087&productId=1070129528&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'
    try:
        result = requests.get(url, headers=kv)
        result.raise_for_status()
        result_json_str = result.text[26:-2]  # json字符串
        result_dict = json.loads(result_json_str)  # 將json轉換為字典
        result_json_comments = result_dict['comments']  # 經過分析,發現評論都在'comments',返回列表套字典
        for i in result_json_comments:  # 真正的評論在'content
            print(i['content'])
    except Exception as e:
        print(e)

if __name__ == '__main__':
    spider_comment()

4.數據保存

數據提取后我們需要將他們保存起來,一般保存數據的格式主要有:文件、數據庫、內存這三大類。今天我們就將數據保存為txt文件格式,因為操作文件相對簡單同時也能滿足我們的后續數據分析的需求。

import json
import os
import random
import time

import requests

comment_file_path = 'jd_comment.txt'


def spider_comment():
"""爬取狗東評論數據"""
kv = {'Referer': 'https://item.jd.com/1070129528.html',
'Sec-Fetch-Mode': 'no-cors',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}

url = 'https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv9086&productId=1070129528&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'
try:
result = requests.get(url, headers=kv)
result.raise_for_status()
result_json_str = result.text[26:-2] # json字符串
result_dict = json.loads(result_json_str) # 將json轉換為字典
result_json_comments = result_dict['comments'] # 經過分析,發現評論都在'comments',返回列表套字典
for i in result_json_comments: # 真正的評論在'content'
with open(comment_file_path, 'a+', encoding='utf-8') as f:
f.write(i['content'] + '\n')
except Exception as e:
print(e)

if __name__ == '__main__':
spider_comment()

5.批量爬取

我們剛剛完成一頁數據爬取、提取、保存之后,我們來研究一下如何批量抓取?

做過web的同學可能知道,有一項功能是我們必須要做的,那便是分頁。何為分頁?為何要做分頁?

我們在瀏覽很多網頁的時候常常看到“下一頁”這樣的字眼,其實這就是使用了分頁技術,因為向用戶展示數據時不可能把所有的數據一次性展示,所以采用分頁技術,一頁一頁的展示出來。

讓我們再回到最開始的加載評論數據的url:

https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv9087&productId=1070129528&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1

我們可以看到鏈接里面有兩個參數page=0&pageSize=10,page表示當前的頁數,pageSize表示每頁多少條,那這兩個數據直接去數據庫limit數據。

老司機一眼便可以看出這就是分頁的參數,但是有同學會說:如果我是老司機還干嘛看你的文章?所以我教大家如何來找到這個分頁參數

回到某東的商品頁,我們將評價頁面拉到最底下,發現有分頁的按鈕,然后我們在調試窗口清空之前的請求記錄。

 

 清空之前的請求記錄之后,我們點擊上圖紅框分頁按鈕的數字2,代表這第二頁,然后復制第一條評價去調試窗口搜索,最后找到請求鏈接。

和上面的步驟一樣。

 

 然后我們比較第一頁評價與第二頁評價的url有何區別,可以很容易發下只有page不同。

這里也就驗證了猜想:page表示當前的頁數,pageSize表示每頁多少條。而且我們還能得出另一個結論:第一個page=0,第二頁page=1 然后依次往后。有同學會問:為什么第一頁不是1,而是0,因為在數據庫中一般的都是從0開始計數,編程行業很多數組列表都是從0開始計數。

好了,知道分頁規律之后,我們只要在每次請求時將page參數遞增不就可以批量抓取了嗎?我們來寫代碼吧!

import json
import os
import random
import time

import requests

comment_file_path = 'jd_comment.txt'


def spider_comment(page):
    """爬取狗東評論數據"""
    kv = {'Referer': 'https://item.jd.com/1070129528.html',
          'Sec-Fetch-Mode': 'no-cors',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}

    url = 'https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv9086&productId=1070129528&score=0&sortType=5&page=%s&pageSize=10&isShadowSku=0&fold=1' % page
    try:
        result = requests.get(url, headers=kv)
        result.raise_for_status()
        result_json_str = result.text[26:-2]  # json字符串
        result_dict = json.loads(result_json_str)  # 將json轉換為字典
        result_json_comments = result_dict['comments']   # 經過分析,發現評論都在'comments',返回列表套字典
        for i in result_json_comments:  # 真正的評論在'content'
            with open(comment_file_path, 'a+', encoding='utf-8') as f:
                f.write(i['content'] + '\n')
    except Exception as e:
        print(e)


def batch_spider_comment():
    # 寫入文件之前,先清空之前的數據
    if os.path.exists(comment_file_path):
        os.remove(comment_file_path)
    for i in range(100):
        spider_comment(i)
        # 模擬用戶瀏覽,設置一個爬蟲間隔,防止ip被封
        time.sleep(random.random() * 5)


if __name__ == '__main__':
    batch_spider_comment()

6.數據清洗以及生成詞雲。

數據成功保存之后我們需要對數據進行分詞清洗,對於分詞我們使用著名的分詞庫jieba

import jieba
import numpy as np
from PIL import Image
from wordcloud import WordCloud
import matplotlib.pyplot as plt


comment_file_path = 'jd_comment.txt'

def cut_word():
    '''
    對數據分詞
    :return: 分詞后的數據
    '''
    with open(comment_file_path, 'r', encoding='utf-8') as f:
        comment_txt = f.read()

        wordlist = jieba.cut(comment_txt, cut_all=True)
        word_str = ' '.join(wordlist)
        #print(word_str)
        return word_str


def create_word_cloud():
    """生成詞雲"""
    # 設置詞雲形狀圖片
    coloring = np.array(Image.open('wawa.jpg'))
    # 設置詞雲一些配置,如字體,背景色,詞雲形狀,大小
    wc = WordCloud(background_color='white', max_words=2000,mask=coloring, scale=4,
                   max_font_size=50, random_state=42, font_path='C:\Windows\Fonts\msyhbd.ttc')
    # 生成詞雲
    wc.generate(cut_word())

    # 在只設置mask情況下,會擁有一個圖形形狀的詞雲
    plt.imshow(wc, interpolation="bilinear")
    plt.axis('off')
    plt.figure()
    plt.show()



if __name__ == '__main__':
    create_word_cloud()

注意:font_path是選擇字體的路徑,如果不設置默認字體可能不支持中文,豬哥選擇的是Mac系統自帶的宋體字!

最終結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM