整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          用Python識別和提取pdf中的文字,并寫入 CS

          用Python識別和提取pdf中的文字,并寫入 CSV 文件腳本

          . 前言

          掃描件一直受大眾青睞,任何紙質(zhì)資料在掃描之后進(jìn)行存檔,想使用時手機就能打開,省心省力。但是掃描件的優(yōu)點也恰恰造成了它的一個缺點,因為是通過電子設(shè)備掃描,所以出來的是圖像,如果想要處理文件上的內(nèi)容,直接操作是無法實現(xiàn)的。

          那要是想要引用其中的內(nèi)容怎么辦呢?別擔(dān)心,Python幫你解決問題。

          2. 需求描述

          現(xiàn)有一份pdf掃描件,我們想把其中的文字提取出來并且分三列寫入csv文檔,內(nèi)容及效果如下:

          pdfexample

          csvexample

          3. 開始動手動腦

          pdf掃描件是文檔掃描成電腦圖片格式后轉(zhuǎn)化成的,提取其中的文字就相當(dāng)于識別圖片內(nèi)的文字。所以,我們的工作就是將pdf轉(zhuǎn)成圖片,再用ocr工具提取圖片中的文字。

          3.1 安裝相關(guān)第三方包

          pip3 install pdf2image pytesseract

          3.2 導(dǎo)入需要用到的第三方庫

          import os   #處理文件
          from pdf2image import convert_from_path  # pdf轉(zhuǎn)圖片
          import pytesseract  # 識別圖片文字
          import csv  # 處理csv文件

          3.3 讀取pdf文件,并識別內(nèi)容

          tess_ocr(pdf_path, lang, first_page, last_page)

          將pdf文件拆分成圖片,并提取文字寫入文本文件

          • pdf_path:pdf文件的存儲路徑
          • image:代表PDF文檔每頁的PIL圖像列表
          • first_page :允許設(shè)置由pdftoppm處理的第一個頁面;
          • last_page:允許設(shè)置最后一頁由pdftoppm處理
          • fmt:允許指定輸出格式。目前支持的格式是jpg、png和ppm;
          • output_folder:圖片保存路徑
          def tess_ocr(pdf_path, lang,first_page,last_page):
            # 創(chuàng)建一個和pdf同名的文件夾
             images=convert_from_path(pdf_path, fmt='png',first_page=first_page,last_page=last_page,output_folder=imagefolder,userpw='site')  # 轉(zhuǎn)成圖片
            text=''
            for img in images:    
                 text +=pytesseract.image_to_string(img, lang=lang) # 識別圖片文字  
                 with open(r'example\data.txt' 'a', encoding='utf-8') as f: #寫入txt文件
                 f.write(text)

          運行結(jié)果

          生成一個同名的文件夾存放拆分的圖片,接著提取圖片文字寫入data.txt

          image-20211215212147760

          運行問題

          “ 問題拋出1:

          pdf2image.exceptions.PDFInfoNotInstalledError: Unable to get page count. Is poppler installed and in PATH? ”

          解決措施:下載 poppler。

          >1 方法一:設(shè)置環(huán)境變量 poppler/bin;

          >2 方法二:

          參數(shù)指定絕對路徑:

          images=convert_from_path(pdf_path=pdf_file_path, poppler_path=r'poppler中bin文件所在地址')

          “ 問題拋出2:

          pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in your PATH. See README file for more information. ”

          解決措施:額外下載安裝tesseract-ocr并配置環(huán)境變量。

          3.4 對識別的數(shù)據(jù)進(jìn)行處理,寫入csv文件

          modification(infile, outfile)

          清洗生成的文本文檔

          • infile:需要進(jìn)行處理的文件地址
          • outfile:處理后生成的新文件的地址
          def modification(infile, outfile):
            infp=open(infile, "r",encoding='utf-8')
            outfp=open(outfile, "w",encoding='utf-8')
            lines=infp.readlines() #返回列表,包含所有的行。
            #依次讀取每行
            for li in lines:  
              if li.split():             #str.split(str="", num=string.count(str)),過濾文件中的空行  
                # 根據(jù)識別情況對數(shù)據(jù)進(jìn)行清洗  
                li=li.replace('[', ' ').replace(']', '')  
                outfp.writelines(li)    
            infp.close()
            outfp.close()
          

          運行結(jié)果

          生成一個新的txt文件,新文件刪除了data.txt中的空行,將原文件中錯誤識別的內(nèi)容替換成正確的。

          writercsv(intxt,outcsv)

          將文本文件按空格分列寫入csv表格

          • intxt:文本文件地址
          • outcsv:新生成的csv文件
          def writercsv(intxt,outcsv):
            # 使用newlines=''可保證存儲的數(shù)據(jù)不空行。
            csvFile=open(outcsv, 'a',newline='', encoding='utf-8') 
            writer=csv.writer(csvFile)
            csvRow=[]
            f=open(intxt,'r',encoding='utf-8')
            for line in f:
                csvRow=line.split() #以空格為分隔符
                if len(csvRow)>1 and len(csvRow)<=3:  #約束條件,視情況而定
                   writer.writerow(csvRow)
            f.close()
            csvFile.close()

          運行結(jié)果

          生成一個三列csv文件,第一列是英文名,第二列是中文名,第三列是所在國家

          image-20211215204846623

          image-20211215204941725

          總結(jié)

          通過本次學(xué)習(xí)實現(xiàn)了從掃描件中提取文字、把內(nèi)容按要求寫進(jìn)不同格式的文檔的需求。

          最初以為提取pdf的庫也適用于掃描件,嘗試了Pdfplumber庫和PyPDF2庫。

          實踐發(fā)現(xiàn)Pdfplumber只能識別掃描件pdf中的水印,不適用于掃描件的pdf,而PyPDF2庫運行報錯:NotImplementedError: only algorithm code 1 and 2 are supported。

          原因是這個被加密的pdf可能是從高版本的acrobot中來的,所以對應(yīng)的加密算法代號為‘4’,然而,現(xiàn)有的pypdf2模塊并只支持加密算法代號為‘1’或者‘2’的pdf加密文件。

          參考來源:https://developer.51cto.com/article/702898.html

          篇文章是python爬蟲系列的第三篇,介紹如何抓取京東商城商品評論信息,并對這些評論信息進(jìn)行分析和可視化。下面是要抓取的商品信息,一款女士文胸。這個商品共有紅色,黑色和膚色三種顏色, 70B到90D共18個尺寸,以及超過700條的購買評論。

          京東商品評論信息是由JS動態(tài)加載的,所以直接抓取商品詳情頁的URL并不能獲得商品評論的信息。因此我們需要先找到存放商品評論信息的文件。這里我們使用Chrome瀏覽器里的開發(fā)者工具進(jìn)行查找。

          具體方法是在商品詳情頁點擊鼠標(biāo)右鍵,選擇檢查,在彈出的開發(fā)者工具界面中選擇Network,設(shè)置為禁用緩存(Disable cache)和只查看JS文件。然后刷新頁面。頁面加載完成后向下滾動鼠標(biāo)找到商品評價部分,等商品評價信息顯示出來后,在下面Network界面的左側(cè)篩選框中輸入productPageComments,這時下面的加載記錄中只有一條信息,這里包含的就是商品詳情頁的商品評論信息。點擊這條信息,在右側(cè)的Preview界面中可以看到其中包含了當(dāng)前頁面中的評論信息。(抓取價格信息輸入prices)。

          復(fù)制這條信息,并把URL地址放在瀏覽器中打開,里面包含了當(dāng)前頁的商品評論信息。這就是我們要抓取的URL地址。https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv100&productId=10001234327&score=0&sortType=5&page=0&pageSize=10

          仔細(xì)觀察這條URL地址可以發(fā)現(xiàn),其中productId=10001234327是當(dāng)前商品的商品ID。與商品詳情頁URL中的ID一致。而page=0是頁碼。如果我們要獲取這個商品的所有評論,只需要更改page后面的數(shù)字即可。

          在獲得了商品評論的真實地址以及URL地址的規(guī)律后,我們開始使用python抓取這件商品的700+條評論信息。并對這些信息進(jìn)行處理和分析。

          開始前的準(zhǔn)備工作

          在開始抓取之前先要導(dǎo)入各種庫文件,這里我們分別介紹下需要導(dǎo)入的每個庫文件的名稱以及在數(shù)據(jù)抓取和分析中的作用。requests用于進(jìn)行頁面抓取,time用于設(shè)置抓取過程中的Sleep時間,random用于生產(chǎn)隨機數(shù),這里的作用是將抓取頁面的順序打亂,re用于在抓取后的頁面代碼中提取需要的信息,numpy用于常規(guī)的指標(biāo)計算,pandas用于進(jìn)行數(shù)據(jù)匯總和透視分析,matplotlib用于繪制各站圖表,jieba用于對評論內(nèi)容進(jìn)行分詞和關(guān)鍵詞提取。

          #導(dǎo)入requests庫(請求和頁面抓取)

          import requests

          #導(dǎo)入time庫(設(shè)置抓取Sleep時間)

          import time

          #導(dǎo)入random庫(生成亂序隨機數(shù))

          import random

          #導(dǎo)入正則庫(從頁面代碼中提取信息)

          import re

          #導(dǎo)入數(shù)值計算庫(常規(guī)計算)

          import numpy as np

          #導(dǎo)入科學(xué)計算庫(拼表及各種分析匯總)

          import pandas as pd

          #導(dǎo)入繪制圖表庫(數(shù)據(jù)可視化)

          import matplotlib.pyplot as plt

          #導(dǎo)入結(jié)巴分詞庫(分詞)

          import jieba as jb

          #導(dǎo)入結(jié)巴分詞(關(guān)鍵詞提取)

          import jieba.analyse

          將爬蟲偽裝成瀏覽器

          導(dǎo)入完庫文件后,還不能直接進(jìn)行抓取,因為這樣很容易被封。我們還需要對爬蟲進(jìn)行偽裝,是爬蟲看起來更像是來自瀏覽器的訪問。這里主要的兩個工作是設(shè)置請求中的頭文件信息以及設(shè)置Cookie的內(nèi)容。

          頭文件信息很容易找到,在Chrome的開發(fā)者工具中選擇Network,刷新頁面后選擇Headers就可以看到本次訪問的頭文件信息,里面包含了一些瀏覽器的技術(shù)參數(shù)和引薦來源信息。將這些信息直接添加到代碼中就可以,這里我們將頭部信息保存在headers中。

          #設(shè)置請求中頭文件的信息

          headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',

          'Accept':'text/html;q=0.9,*/*;q=0.8',

          'Accept-Charset':'ISO-8859-1,utf-8;q=0.7,*;q=0.3',

          'Connection':'close',

          'Referer':'https://www.jd.com/'

          }

          在查看頭文件信息的旁邊還有一個Cookies標(biāo)簽,點擊進(jìn)去就是本次訪問的Cookies信息。這里的Cookies信息與前面頭文件中的Cookie信息一致,不過這里更加清晰。把Request Cookies信息復(fù)制到代碼中即可,這里我們將Request Cookies信息保存在Cookie中。

          #設(shè)置Cookie的內(nèi)容

          cookie={'TrackID':'1_VWwvLYiy1FUr7wSr6HHmHhadG8d1-Qv-TVaw8JwcFG4EksqyLyx1SO7O06_Y_XUCyQMksp3RVb2ezA',

          '__jda':'122270672.1507607632.1423495705.1479785414.1479794553.92',

          '__jdb':'122270672.1.1507607632|92.1479794553',

          '__jdc':'122270672',

          '__jdu':'1507607632',

          '__jdv':'122270672|direct|-|none|-|1478747025001',

          'areaId':'1',

          'cn':'0',

          'ipLoc-djd':'1-72-2799-0',

          'ipLocation':'%u5317%u4EAC',

          'mx':'0_X',

          'rkv':'V0800',

          'user-key':'216123d5-4ed3-47b0-9289-123456',

          'xtest':'4657.553.d9798cdf31c02d86b8b81cc119d94836.b7a782741f667201b54880c925faec4b'}

          抓取商品評論信息

          設(shè)置完請求的頭文件和Cookie信息后,我們開始抓取京東商品評論的信息。前面分析URL的時候說過,URL中包含兩個重要的信息,一個是商品ID,另一個是頁碼。這里我們只抓取一個商品的評論信息,因此商品ID不需要更改。但這個商品的評論有700+條,也就是有近80頁需要抓取,因此頁碼不是一個固定值,需要在0-80之間變化。這里我們將URL分成兩部分,通過隨機生成頁碼然后拼接URL的方式進(jìn)行抓取。

          #設(shè)置URL的第一部分

          url1='https://sclub.jd.com/comment/productPageComments.action?productId=10001234327&score=0&sortType=3&page='

          #設(shè)置URL的第二部分

          url2='&pageSize=10&callback=fetchJSON_comment98vv41127'

          #亂序輸出0-80的唯一隨機數(shù)

          ran_num=random.sample(range(80), 80)

          為了使抓取過程看起來更加隨機,我們沒有從第1頁一直抓取到第80頁。而是使用random生成0-80的唯一隨機數(shù),也就是要抓取的頁碼編號。然后再將頁碼編號與兩部分URL進(jìn)行拼接。這里我們只知道商品有700+的評論,但并不知道具體數(shù)字,所以抓取范圍定位從0-80頁。

          下面是具體的抓取過程,使用for循環(huán)每次從0-80的隨機數(shù)中找一個生成頁碼編號,與兩部分的URL進(jìn)行拼接。生成要抓取的URL地址并與前面設(shè)置好的頭文件信息和Cookie信息一起發(fā)送請求獲取頁面信息。將獲取到的頁面信息進(jìn)行匯總。每次請求間休息5秒針,避免過于頻繁的請求導(dǎo)致返回空值。

          #拼接URL并亂序循環(huán)抓取頁面

          for i in ran_num:

          a=ran_num[0]

          if i==a:

          i=str(i)

          url=(url1+i+url2)

          r=requests.get(url=url,headers=headers,cookies=cookie)

          html=r.content

          else:

          i=str(i)

          url=(url1+i+url2)

          r=requests.get(url=url,headers=headers,cookies=cookie)

          html2=r.content

          html=html + html2

          time.sleep(5)

          print("當(dāng)前抓取頁面:",url,"狀態(tài):",r)

          在抓取的過程中輸出每一步抓取的頁面URL以及狀態(tài)。通過下面的截圖可以看到,在page參數(shù)后面的頁碼是隨機生成的并不連續(xù)。

          抓取完80個頁面后,我們還需要對頁面進(jìn)行編碼。完成編碼后就可以看到其中所包含的中文評論信息了。后面大部分苦逼的工作就是要對這些評論信息進(jìn)行不斷提取和反復(fù)的清洗。

          #對抓取的頁面進(jìn)行編碼

          html=str(html, encoding="GBK")

          這里建議將抓取完的數(shù)據(jù)存儲在本地,后續(xù)工作可以直接從本地打開文件進(jìn)行清洗和分析工作。避免每次都要重新抓取數(shù)據(jù)。這里我們將數(shù)據(jù)保存在桌面的page.txt文件中。

          #將編碼后的頁面輸出為txt文本存儲

          file=open("c:\Users \Desktop\page.txt", "w")

          file.write(html)

          file.close()

          讀取文件也比較簡單,直接open加read函數(shù)就可以完成了。

          #讀取存儲的txt文本文件

          html=open('c:\Users\ Desktop\page.txt', 'r').read()

          提取信息并進(jìn)行數(shù)據(jù)清洗

          京東的商品評論中包含了很多有用的信息,我們需要將這些信息從頁面代碼中提取出來,整理成數(shù)據(jù)表以便進(jìn)行后續(xù)的分析工作。這里應(yīng)該就是整個過程中最苦逼的數(shù)據(jù)提取和清洗工作了。我們使用正則對每個字段進(jìn)行提取。對于特殊的字段在通過替換等方式進(jìn)行提取和清洗。

          下面是提取的第一個字段userClient,也就是用戶發(fā)布評論時所使用的設(shè)備類型,這類的字段提取還比較簡單,一行代碼搞定。查看一下提取出來的字段還比較干凈。使用同樣的方法我們分別提取了以下這些字段的內(nèi)容。

          #使用正則提取userClient字段信息

          userClient=re.findall(r',"usefulVoteCount".*?,"userClientShow":(.*?),',html)

          #使用正則提取userLevel字段信息

          userLevel=re.findall(r'"referenceImage".*?,"userLevelName":(.*?),',html)

          #使用正則提取productColor字段信息

          productColor=re.findall(r'"creationTime".*?,"productColor":(.*?),',html)

          #使用正則提取recommend字段信息

          recommend=re.findall(r'"creationTime".*?,"recommend":(.*?),',html)

          #使用正則提取nickname字段信息

          nickname=re.findall(r'"creationTime".*?,"nickname":(.*?),',html)

          #使用正則提取userProvince字段信息

          userProvince=re.findall(r'"referenceImage".*?,"userProvince":(.*?),',html)

          #使用正則提取usefulVoteCount字段信息

          usefulVoteCount=re.findall(r'"referenceImage".*?,"usefulVoteCount":(.*?),',html)

          #使用正則提取days字段信息

          days=re.findall(r'"usefulVoteCount".*?,"days":(.*?)}',html)

          #使用正則提取score字段信息

          score=re.findall(r'"referenceImage".*?,"score":(.*?),',html)

          還有一些字段比較負(fù)責(zé),無法通過正則一次提取出來,比如isMobile字段,有些值的后面還有大括號。這就需要進(jìn)一步的提取和清洗工作。

          #使用正則提取isMobile字段信息

          isMobile=re.findall(r'"usefulVoteCount".*?,"isMobile":(.*?),',html)

          使用for循環(huán)配合替換功能將字段中所有的}替換為空。替換完成后字段看起來干凈多了。

          #替換掉最后的}

          mobile=[]

          for m in isMobile:

          n=m.replace('}','')

          mobile.append(n)

          productSize字段中包含了胸圍和杯罩兩類信息,為了獲得獨立的杯罩信息需要進(jìn)行二次提取,將杯罩信息單獨保存出來。

          #使用正則提取productSize字段信息

          productSize=re.findall(r'"creationTime".*?,"productSize":(.*?),',html)

          使用for循環(huán)將productSize中的第三個字符杯罩信息提取出來,并保持在cup字段中。

          #提取杯罩信息

          cup=[]

          for s in productSize:

          s1=s[3]

          cup.append(s1)

          創(chuàng)建評論的日期信息僅依靠正則提取出來的信息還是比較亂,無法直接使用。因此也需要進(jìn)行二次提取。下面是使用正則提取出的結(jié)果。

          #使用正則提取時間字段信息

          creationTime1=re.findall(r'"creationTime":(.*?),"referenceName',html)

          日期和時間信息處于前20個字符,在二次提取中根據(jù)這個規(guī)律直接提起每個條目的前20個字符即可。將日期和時間單獨保存為creationTime。

          #提取日期和時間

          creationTime=[]

          for d in creationTime1:

          date=d[1:20]

          creationTime.append(date)

          在上一步日期和時間的基礎(chǔ)上,我們再進(jìn)一步提取出單獨的小時信息,方法與前面類似,提取日期時間中的第11和12個字符,就是小時的信息。提取完保存在hour字段以便后續(xù)的分析和匯總工作。

          #提取小時信息

          hour=[]

          for h in creationTime:

          date=h[10:13]

          hour.append(date)

          最后要提取的是評論內(nèi)容信息,頁面代碼中包含圖片的評論信息是重復(fù)的,因此在使用正則提取完后還需要對評論信息進(jìn)行去重。

          #使用正則提取評論信息

          content=re.findall(r'"guid".*?,"content":(.*?),',html)

          使用if進(jìn)行判斷,排除掉所有包含圖片的評論信息,已達(dá)到評論去重的目的。

          #對提取的評論信息進(jìn)行去重

          content_1=[]

          for i in content:

          if not "img" in i:

          content_1.append(i)

          完成所有字段信息的提取和清洗后,將這些字段組合在一起生成京東商品評論數(shù)據(jù)匯總表。下面是創(chuàng)建數(shù)據(jù)表的代碼。數(shù)據(jù)表生成后還不能馬上使用,需要對字段進(jìn)行格式設(shè)置,例如時間和日期字段和一些包含數(shù)值的字段。具體的字段和格式設(shè)置依據(jù)后續(xù)的分析過程和目的。這里我們將creationTime設(shè)置為時間格式,并設(shè)置為數(shù)據(jù)表的索引列。將days字段設(shè)置為數(shù)值格式。

          #將前面提取的各字段信息匯總為table數(shù)據(jù)表,以便后面分析

          table=pd.DataFrame({'creationTime':creationTime,'hour':hour,'nickname':nickname,'productColor':productColor,'productSize':productSize,'cup':cup,'recommend':recommend,'mobile':mobile,'userClient':userClient,'userLevel':userLevel,'userProvince':userProvince,'usefulVoteCount':usefulVoteCount,'content_1':content_1,'days':days,'score':score})

          #將creationTime字段更改為時間格式

          table['creationTime']=pd.to_datetime(table['creationTime'])

          #設(shè)置creationTime字段為索引列

          table=table.set_index('creationTime')

          #設(shè)置days字段為數(shù)值格式

          table['days']=table['days'].astype(np.int64)

          #查看整理完的數(shù)據(jù)表

          table.head()

          這里建議再次保存清洗和預(yù)處理完的數(shù)據(jù)表。我們這里將數(shù)據(jù)表保存為csv格式。到了這一步可以選擇在Excel中完成后續(xù)的數(shù)據(jù)分析和可視化過程,也可以繼續(xù)在python中完成。我們這里選擇繼續(xù)在python中完成后續(xù)的數(shù)據(jù)分析和可視化工作。

          #保存table數(shù)據(jù)表

          table.to_csv('jd_table.csv')

          數(shù)據(jù)分析及可視化

          分月評論數(shù)據(jù)變化趨勢

          首先查看京東商品評論的時間變化趨勢情況,大部分用戶在購買商品后會在10天以內(nèi)進(jìn)行評論,因此我們可以近似的認(rèn)為在一個月的時間維度中評論時間的變化趨勢代表了用戶購買商品的變化趨勢。

          按月的維度對數(shù)據(jù)表進(jìn)行匯總,并提取每個月的nickname的數(shù)量。下面是具體的代碼和分月數(shù)據(jù)。

          #對數(shù)據(jù)表按月進(jìn)行匯總并生成新的月度匯總數(shù)據(jù)表

          table_month=table.resample('M',how=len)

          #提取按月匯總的nickname

          month=table_month['nickname']

          數(shù)據(jù)范圍從2015年11月到2016年11月。使用柱狀圖對分月數(shù)據(jù)進(jìn)行可視化。從圖表中可以看到2016年6月是評論的高峰,也可以近似的認(rèn)為這個時間段是用戶購買該商品的高峰(6月18日是京東店慶日)。排除2016年6月和不完整的11月數(shù)據(jù),整齊趨勢中冬季評論量較低,夏季較高。這是由于該商品的季節(jié)屬性導(dǎo)致的,超薄胸罩更適合夏天佩戴(這個屬性我們是在用戶的評論中發(fā)現(xiàn)的,在京東的商品介紹中并不明顯,只在標(biāo)題中以”薄杯”說明)。

          #繪制分月評論數(shù)量變化趨勢圖

          plt.rc('font', family='STXihei', size=9)

          a=np.array([1,2,3,4,5,6,7,8,9,10,11,12,13])

          plt.bar([1,2,3,4,5,6,7,8,9,10,11,12,13],month,color='#99CC01',alpha=0.8,align='center',edgecolor='white')

          plt.xlabel('月份')

          plt.ylabel('評論數(shù)量')

          plt.title('分月評論數(shù)量變化趨勢')

          plt.legend(['評論數(shù)量'], loc='upper right')

          plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)

          plt.xticks(a,('15-11','12','16-01','02','03','04','05','06','07','08','09','10','11'))

          plt.show()

          通過篩選將數(shù)據(jù)表分為使用移動設(shè)備和未使用移動設(shè)備兩個表格,再分別查看和對比評論變化趨勢。

          #在table表中篩選使用移動設(shè)備的條目并創(chuàng)建新表

          mobile_t=table.loc[table["mobile"]=="true"]

          #在table中篩選沒有使用移動設(shè)備的條目并創(chuàng)建新表

          mobile_f=table.loc[table["mobile"]=="false"]

          #按月匯總使用移動設(shè)備的數(shù)據(jù)

          mobile_t_m=mobile_t.resample('M',how=len)

          #按月匯總不使用移動設(shè)備的數(shù)據(jù)

          mobile_f_m=mobile_f.resample('M',how=len)

          #提取使用移動設(shè)備的按月匯總nickname

          mobile_y=mobile_t_m['nickname']

          #提取沒有使用移動設(shè)備的按月匯總nickname

          mobile_n=mobile_f_m['nickname']

          從結(jié)果中可以看出使用移動設(shè)備進(jìn)行評論的用戶在所有的時間段中都要明顯高于使用PC的用戶。

          #繪制PC與移動設(shè)備評論數(shù)量變化趨勢圖

          plt.subplot(2, 1, 1)

          plt.plot(mobile_y,'go',mobile_y,'g-',color='#99CC01',linewidth=3,markeredgewidth=3,markeredgecolor='#99CC01',alpha=0.8)

          plt.ylabel('移動設(shè)備評論數(shù)量')

          plt.title('PC與移動設(shè)備評論數(shù)量變化趨勢')

          plt.subplot(2, 1, 2)

          plt.plot(mobile_n,'go',mobile_n,'g-',color='#99CC01',linewidth=3,markeredgewidth=3,markeredgecolor='#99CC01',alpha=0.8)

          plt.xlabel('月份')

          plt.ylabel('PC評論數(shù)量')

          plt.show()

          24小時評論數(shù)量變化趨勢

          按小時維度對評論數(shù)據(jù)進(jìn)行匯總,查看用戶在24小時中的評論變化趨勢。這里需要說明的是24小時趨勢只能反映用戶登錄京東商城的趨勢,并不能近似推斷用戶購買商品的時間趨勢。

          #按24小時分別對table表中的nickname進(jìn)行計數(shù)

          hour_group=table.groupby('hour')['nickname'].agg(len)

          從24小時評論趨勢圖來看,發(fā)布商品評論的趨勢與作息時間一致,并且每日的閑暇時間是發(fā)布評論的高峰。如早上的8點,中午的12點和晚上的22點,是一天24小時中的三個評論高峰點。

          #匯總24小時評論數(shù)量變化趨勢圖

          plt.rc('font', family='STXihei', size=9)

          a=np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23])

          plt.bar([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],hour_group,color='#99CC01',alpha=0.8,align='center',edgecolor='white')

          plt.xlabel('24小時')

          plt.ylabel('評論數(shù)量')

          plt.title('24小時評論數(shù)量變化趨勢')

          plt.legend(['評論數(shù)量'], loc='upper right')

          plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)

          plt.xticks(a,('0','1','2','3','4','5','6','7','8','9','10','11','12''13','14','15','16','17','18','19','20','21','22','23'))

          plt.show()

          將24小時的評論數(shù)量分為移動設(shè)備和未使用移動設(shè)備,查看并對比這兩者的變化趨勢情況。

          #在使用移動設(shè)備的表中按24小時對nickname進(jìn)行計數(shù)

          mobile_y_h=mobile_t.groupby('hour')['nickname'].agg(len)

          #在沒有使用移動設(shè)備的表中按24小時對nickname進(jìn)行計算

          mobile_n_h=mobile_f.groupby('hour')['nickname'].agg(len)

          移動設(shè)備的評論數(shù)量在24小時中的各個時間段都要高于PC的評論數(shù)量,并且在晚間更加活躍,持續(xù)時間高于PC端。這里我們產(chǎn)生了一個疑問,在一天中的工作時間段中,大部分用戶都會在電腦旁,但為什么這些時間段里移動設(shè)備的評論數(shù)量也要高于PC端呢?這是否與胸罩這個產(chǎn)品的私密性有關(guān)聯(lián)。用戶不希望別人看到自己購買的商品或評論的內(nèi)容,所以選擇使用移動設(shè)備進(jìn)行評論?

          #匯總PC與移動設(shè)備24小時評論數(shù)量變化趨勢

          plt.subplot(2, 1, 1)

          plt.plot(mobile_y_h,'go',mobile_y_h,'g-',color='#99CC01',linewidth=3,markeredgewidth=3,markeredgecolor='#99CC01',alpha=0.8)

          plt.ylabel('移動設(shè)備評論數(shù)量')

          plt.title('PC與移動設(shè)備24小時評論數(shù)量變化趨勢')

          plt.subplot(2, 1, 2)

          plt.plot(mobile_n_h,'go',mobile_n_h,'g-',color='#99CC01',linewidth=3,markeredgewidth=3,markeredgecolor='#99CC01',alpha=0.8)

          plt.xlabel('24小時')

          plt.ylabel('PC評論數(shù)量')

          plt.show()

          用戶客戶端分布情況

          前面的分析中,我們看到使用移動設(shè)備進(jìn)行評論的用戶要遠(yuǎn)高于PC端的用戶,下面我們對用戶所使用的設(shè)備分布情況進(jìn)行統(tǒng)計。首先在數(shù)據(jù)表中按用戶設(shè)備(userClient)對nickname字段進(jìn)行計數(shù)匯總。

          #在table表中按userClient對數(shù)據(jù)進(jìn)行匯總

          userClient_group=table.groupby('userClient')['nickname'].agg(len)

          從用戶客戶端分布情況來看,移動端的設(shè)備占大多數(shù),其中使用iphone的用戶要高于Android用戶。由于微信購物和QQ購物單獨被分了出來,無法確定設(shè)備,因此單獨進(jìn)行對比。使用微信購物渠道的用戶要高于QQ購物。

          #匯總用戶客戶端分布情況

          plt.rc('font', family='STXihei', size=9)

          a=np.array([1,2,3,4,5,6])

          plt.bar([1,2,3,4,5,6],userClient_group,color='#99CC01',alpha=0.8,align='center',edgecolor='white')

          plt.xlabel('客戶端分布')

          plt.ylabel('評論數(shù)量')

          plt.title('用戶客戶端分布情況')

          plt.legend(['評論數(shù)量'], loc='upper right')

          plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)

          plt.ylim(0,300)

          plt.xticks(a,('PC','Android','iPad','iPhone','微信購物','QQ購物'))

          plt.show()

          購買后評論天數(shù)分布

          在購買后評論天數(shù)方面,我們將用戶發(fā)布評論與購買的時間間隔分為7組,分別為購買后1-5天內(nèi),5-10天內(nèi),10-15天內(nèi),15-20天內(nèi),20-25天內(nèi),25-30天內(nèi),以及大于30天。然后統(tǒng)計并對比用戶在不同時間區(qū)間內(nèi)發(fā)布評論的數(shù)量情況。

          #設(shè)置分組條件,并對table表中的days字段進(jìn)行分組

          bins=[0, 5, 10, 15, 20, 25, 30, 92]

          day_group=['5天', '10天', '15天', '20天', '25天','30天','大于30天']

          table['day_group']=pd.cut(table['days'], bins, labels=day_group)

          #按新設(shè)置的分組對數(shù)據(jù)進(jìn)行匯總

          days_group=table.groupby('day_group')['nickname'].agg(len)

          從圖表中看出,購買后5天以內(nèi)是用戶發(fā)布評論的高峰,也就我們之前推測評論時間趨勢近似于購買時間的依據(jù)。隨著時間的增加評論數(shù)量逐漸下降。

          #繪制用戶購買后評論天數(shù)分布圖

          plt.rc('font', family='STXihei', size=9)

          a=np.array([1,2,3,4,5,6,7])

          plt.bar([1,2,3,4,5,6,7],days_group,color='#99CC01',alpha=0.8,align='center',edgecolor='white')

          plt.xlabel('購買后天數(shù)')

          plt.ylabel('發(fā)布評論數(shù)量')

          plt.title('購買后評論天數(shù)分布')

          plt.legend(['評論數(shù)量'], loc='upper right')

          plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)

          plt.ylim(0,300)

          plt.xticks(a,('5天','10天','15天','20天','25天','30天','大于30天'))

          plt.show()

          商品評分分布情況

          京東商城對商品按5星評分劃分為好評,中評和差評三個等級。我們這里來看下用戶5星評分的分布情況。在數(shù)據(jù)表中score字段中的值表示了用戶對胸罩產(chǎn)品的打分情況。我們按打分情況對數(shù)據(jù)進(jìn)行匯總。

          #在table表中按score對數(shù)據(jù)進(jìn)行匯總

          score_group=table.groupby('score')['nickname'].agg(len)

          從圖表中可以看出,大部分用戶對商品的評分是5星。4星以下的幾乎沒有。但從另一個維度來看,在用戶對最有用評論的投票(usefulVoteCount)中得票最多的是一個1星的評論。

          #繪制用戶評分分布情況圖

          plt.rc('font', family='STXihei', size=9)

          a=np.array([1,2,3,4,5])

          plt.bar([1,2,3,4,5],score_group,color='#99CC01',alpha=0.8,align='center',edgecolor='white')

          plt.xlabel('評分分布')

          plt.ylabel('評論數(shù)量')

          plt.title('用戶評分分布情況')

          plt.legend(['評論數(shù)量'], loc='best')

          plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)

          plt.ylim(0,700)

          plt.xticks(a,('1星','2星','3星','4星','5星'))

          plt.show()

          用戶胸罩尺碼分布情況

          在胸罩的尺寸方面包含兩個信息,一個是胸圍尺寸,另一個是罩杯。我們在前面的清洗過程中對杯罩創(chuàng)建了單獨的字段。下面只對這個字段進(jìn)行匯總統(tǒng)計。

          #在table 表中按cup對數(shù)據(jù)進(jìn)行匯總

          cup_group=table.groupby('cup')['nickname'].agg(len)

          從圖表中可以看出,評論用戶中最多的是B杯罩,其次為C杯罩,D和E的用戶數(shù)量較少。

          #繪制用戶胸罩尺碼分布圖

          plt.rc('font', family='STXihei', size=9)

          a=np.array([1,2,3,4])

          plt.bar([1,2,3,4],cup_group,color='#99CC01',alpha=0.8,align='center',edgecolor='white')

          plt.xlabel('尺碼')

          plt.ylabel('評論數(shù)量')

          plt.title('用戶胸罩尺碼分布情況')

          plt.legend(['評論數(shù)量'], loc='upper right')

          plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)

          plt.ylim(0,350)

          plt.xticks(a,('B','C','D','E'))

          plt.show()

          胸罩顏色偏好分布

          這款胸罩共分為三個顏色,紅色,膚色和黑色。我們按顏色對評論數(shù)據(jù)進(jìn)行匯總,查看用戶對不同胸罩顏色的偏好情況。

          #在table表中按productColor對數(shù)據(jù)進(jìn)行匯總

          color_group=table.groupby('productColor')['nickname'].agg(len)

          從不同顏色的評論數(shù)量上來看,大部分用戶購買的是膚色,購買紅色和黑色的用戶數(shù)量明顯少于膚色。

          #繪制用戶顏色選擇分布圖

          plt.rc('font', family='STXihei', size=9)

          a=np.array([1,2,3])

          plt.bar([1,2,3],color_group,color='#99CC01',alpha=0.8,align='center',edgecolor='white')

          plt.xlabel('顏色分布')

          plt.ylabel('評論數(shù)量')

          plt.title('用戶顏色選擇分布')

          plt.legend(['評論數(shù)量'], loc='upper right')

          plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)

          plt.ylim(0,600)

          plt.xticks(a,('紅色','膚色','黑色'))

          plt.show()

          不同尺碼用戶對胸罩顏色偏好對比

          在前面杯罩尺寸和顏色偏好的基礎(chǔ)上,我們將兩維度進(jìn)行交叉分析,查看并對比不同杯罩尺碼用戶在顏色選擇上是有規(guī)律或明顯差異。這里使用數(shù)據(jù)透視表,將杯罩尺寸設(shè)置為行,顏色設(shè)置為列,對nickname進(jìn)行計數(shù)。

          #使用數(shù)據(jù)透視表對胸罩尺碼和顏色進(jìn)行交叉分析

          color_size=pd.pivot_table(table,index=["cup"],values=["nickname"],columns=["productColor"],aggfunc=len,fill_value=0)

          從數(shù)據(jù)透視表中分別提取出不同尺寸杯罩用戶購買的顏色數(shù)據(jù)。

          #提取B,C,D,E尺碼的顏色分布

          b=color_size.ix['B']

          c=color_size.ix['C']

          d=color_size.ix['D']

          e=color_size.ix['E']

          將不同杯罩尺寸用戶對顏色的選擇分布繪制成四個圖表,進(jìn)行對比和分析。

          #匯總不同胸罩尺碼顏色分布圖

          plt.rc('font', family='STXihei', size=9)

          plt.subplot(2, 2, 1)

          plt.bar([1,2,3],b,color=["#EE9788","#E2D4C9","#151419"],alpha=0.8,align='center',edgecolor='white')

          plt.title('B Cup')

          plt.xticks(a,('紅色','膚色','黑色'))

          plt.subplot(2, 2, 2)

          plt.bar([1,2,3],c,color=["#EE9788","#E2D4C9","#151419"],alpha=0.8,align='center',edgecolor='white')

          plt.title('C Cup')

          plt.ylim(0,200)

          plt.xticks(a,('紅色','膚色','黑色'))

          plt.subplot(2, 2, 3)

          plt.bar([1,2,3],d,color=["#EE9788","#E2D4C9","#151419"],alpha=0.8,align='center',edgecolor='white')

          plt.title('D Cup')

          plt.xticks(a,('紅色','膚色','黑色'))

          plt.subplot(2, 2, 4)

          plt.bar([1,2,3],e,color=["#EE9788","#E2D4C9","#151419"],alpha=0.8,align='center',edgecolor='white')

          plt.title('E,Cup')

          plt.xticks(a,('紅色','膚色','黑色'))

          plt.show()

          在下面的圖表中,B,C,D,E四個杯罩的用戶選擇膚色的數(shù)量都要高于另外兩種顏色。整體差別并不明顯。如果非要說有什么差別的話,C杯罩用戶更偏好紅色?D杯罩更喜歡黑色?這個結(jié)論明顯站不住腳。但有一點可以說,雖然黑色顯瘦但E杯罩的用戶中沒有人選擇黑色。

          D&E Cup用戶城市分布情況

          最后我們再看看下D杯罩和E杯罩用戶的城市分布情況,在數(shù)據(jù)表中并不是所有的評論都有城市信息。因此按城市統(tǒng)計出來的數(shù)據(jù)可能并不準(zhǔn)確,僅供參考。

          首先從數(shù)據(jù)表中篩選出cup值為D和E的數(shù)據(jù),并保存在新的數(shù)據(jù)表中。

          #從table表中提取cup尺寸為D或E的數(shù)據(jù)條目并創(chuàng)建新表

          table_big=table.loc[(table["cup"]=="D")|(table["cup"]=="E")]

          在新的數(shù)據(jù)表中按用戶所在城市(userProvince)進(jìn)行匯總。查看不同城市D和E杯罩的數(shù)量。

          #按城市對數(shù)據(jù)進(jìn)行計數(shù)匯總

          city_group=table_big.groupby('userProvince')['nickname'].agg(len)

          將匯總結(jié)果繪制為圖表,從圖表來看,數(shù)量最多的為未知城市,排除未知城市,北京和廣東的數(shù)量遙遙領(lǐng)先,其次為四川和河南。

          #匯總D和E Cup城市分布圖

          plt.rc('font', family='STXihei', size=9)

          a=np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24])

          plt.barh([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24],city_group,color='#99CC01',alpha=0.8,align='center',edgecolor='white')

          plt.xlabel('評論數(shù)量')

          plt.ylabel('城市')

          plt.title('D Cup和E Cup城市分布')

          plt.legend(['評論數(shù)量'], loc='upper right')

          plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='x',alpha=0.4)

          plt.yticks(a,('未知','上海','云南','內(nèi)蒙古','北京','四川','天津','寧夏','安徽','山東','廣東','江西','江蘇','江西','河北','河南','浙江','湖北','湖南','甘肅','福建','遼寧','重慶','青海','香港'))

          plt.show()

          胸罩評論內(nèi)容語義分析

          前面我們分別對數(shù)據(jù)表中的字段進(jìn)行了統(tǒng)計和分析,文章最后我們對商品的評論內(nèi)容進(jìn)行語義分析,看看大家在這700+條評論中都在說些什么。

          好好先生購買比例

          在人工查看了一些評論內(nèi)容后,我們發(fā)現(xiàn)一些有意思的信息。有一部分評論是老公或男朋友發(fā)的,這說明一些好好先生會幫老婆或女友購買胸罩。那么這部分用戶的比例有多少呢?

          我們把評論中包含有關(guān)鍵詞“老婆”和“女朋友”的評論單獨保存在出來。

          #篩選包含”老婆”和”女朋友”的評論

          content_2=[]

          for i in content_1:

          if "老婆"in i or "女朋友"in i:

          content_2.append(i)

          查看這些包含關(guān)鍵詞的評論內(nèi)容,確實是老公和男朋友來購買胸罩并且發(fā)布的評論。

          #查看評論內(nèi)容

          content_2

          經(jīng)過計算,在這款胸罩產(chǎn)品的評論中,由老公或男朋友購買的比例僅為2.35%。

          #計算老公或男朋友購買胸罩的比例

          len(content_2)/len(content_1)*100

          2.3545706371191137

          商品評論關(guān)鍵詞分析

          回歸到商品評論分析,我們使用結(jié)巴分詞對所有胸罩的評論信息進(jìn)行了分詞,并提取了權(quán)重最高的關(guān)鍵詞列表。

          #文本數(shù)據(jù)格式轉(zhuǎn)換

          word_str=''.join(content_1)

          #提取文字關(guān)鍵詞

          word_rank=jieba.analyse.extract_tags(word_str, topK=20, withWeight=True, allowPOS=())

          #轉(zhuǎn)化為數(shù)據(jù)表

          word_rank=pd.DataFrame(word_rank,columns=['word','rank'])

          #查看關(guān)鍵詞及權(quán)重

          word_rank.sort('rank',ascending=False)

          從高權(quán)重關(guān)鍵詞列表來看,用戶評論以正面信息為主,”不錯”,”舒服”,”喜歡”等主觀感受的正面評論權(quán)重較高。

          結(jié)語

          本篇文章我們從商品評論信息的抓取,清洗到分析和數(shù)據(jù)可視化實現(xiàn)了一個完整的閉環(huán)。整個過程中數(shù)據(jù)的清洗和預(yù)處理是最為復(fù)雜也是耗時最多的工作。由于抓取的數(shù)據(jù)量較少,只有700+條數(shù)據(jù)。因此里面的一些結(jié)論可能沒有代表性,結(jié)論也未必準(zhǔn)確,僅供參考。

          挑戰(zhàn)30天在頭條寫日記#

          TXT(Text File)格式是一種純文本格式的電子文檔,通常用于保存原始的書面文本。它包含書籍、報告、論文、信函等文件內(nèi)容,可以在任何支持文本讀取的設(shè)備上進(jìn)行查看。TXT格式有多個版本,以下是它們的解釋和對應(yīng)的工具:

          1. TXT 1.0:TXT 1.0于1992年推出,是最初的TXT格式。它使用純文本HTML標(biāo)記來定義文檔結(jié)構(gòu),并包含一些基本的文本樣式,如字體、顏色和行距等。由于其簡單性和易讀性,TXT 1.0廣泛用于個人筆記、日記、簡歷等文檔的編寫。
          2. TXT 2.0:TXT 2.0于1994年推出,在TXT 1.0的基礎(chǔ)上進(jìn)行了改進(jìn)。它增加了更多的文本樣式,如段落標(biāo)題、粗體、斜體等,并使用了新的HTML標(biāo)簽來定義樣式和布局。此外,它還支持更多的編程語言,如JavaScript和VBScript,為文檔添加了更多的交互功能。
          3. TXT 3.0:TXT 3.0于1997年推出,在TXT 2.0的基礎(chǔ)上進(jìn)行了進(jìn)一步的改進(jìn)。它使用了UTF-8編碼,提高了文本的可讀性和兼容性,并支持更多的文本格式,如RTF和HTML。此外,它還增加了“超級鏈接”功能,使得文檔中的鏈接更加易于瀏覽。
          4. TXT 4.0:TXT 4.0于2000年推出,是第一個完全支持UTF-8編碼的TXT格式。它提供了更豐富的文本格式支持,如RTF、HTML和CSV,并增加了“搜索引擎”功能,使得文檔內(nèi)容更容易搜索。
          5. TXT 5.0:TXT 5.0于2007年推出,是第一個支持Unicode編碼的TXT格式。它提供了更多的文本格式支持,包括XML、JSON和XML Notebook等,并增加了“富文本”功能,使得文檔內(nèi)容更具可讀性和易于共享。

          對應(yīng)的工具包括純文本文件編輯器(如Notepad、Sublime Text、Atom等)和專門的TXT編輯器(如Textastic、TextFX等)。這些工具可以幫助用戶創(chuàng)建、編輯和管理TXT文件,從而更好地組織和瀏覽網(wǎng)頁內(nèi)容。總之,TXT格式是一種簡單、易讀、易編輯的純文本電子文檔格式,主要用于保存?zhèn)€人筆記、簡歷等個人文檔以及小說、信件、研究報告等原始文本。


          主站蜘蛛池模板: 亚洲宅男精品一区在线观看| 国产色欲AV一区二区三区| 99国产精品欧美一区二区三区| 国产精品资源一区二区| 日本一区二区免费看| 视频一区视频二区在线观看| 亚洲精品一区二区三区四区乱码| 国产一区二区影院| 国产精品一区在线播放| 国产在线一区二区综合免费视频| 大香伊蕉日本一区二区| 无码av人妻一区二区三区四区| 国产午夜福利精品一区二区三区| 日韩一区在线视频| 日韩精品无码一区二区三区免费| 亚洲国产成人久久一区WWW | 日韩一区二区三区在线观看| 99无码人妻一区二区三区免费| 一区二区三区无码视频免费福利 | 无码人妻精品一区二区三18禁| 一区免费在线观看| 国产伦精品一区二区三区免.费| 99在线精品一区二区三区| 精品无码一区二区三区在线| 久久精品动漫一区二区三区| 中文字幕精品一区| 国产高清在线精品一区二区三区| 国产成人无码aa精品一区| 午夜视频一区二区| 国产熟女一区二区三区五月婷| 国产激情一区二区三区小说| 一本久久精品一区二区| 亚洲日韩一区二区三区| 伊人色综合视频一区二区三区| 亚洲一区二区三区播放在线| 亚洲一区在线视频观看| 日韩最新视频一区二区三| 国产一区二区草草影院| 国产福利一区视频| 视频一区视频二区日韩专区| 色综合视频一区二区三区|