天天看點

用python買手機用python買手機

用python買手機

最近某同學一直碎碎念要買P20,我想說此時買似不太明智,但不知從何說起,恰逢放假,閑來無事,遂用python爬取淘寶、京東手機銷售資料做個簡單分析,本部落客要實作了以下功能

  • 爬取淘寶上手機的月銷售資料并存為excel表格
  • 統計淘寶上不同品牌手機的月銷量并以條形圖形式展示
  • 使用python代碼打開浏覽器搜尋京東上手機資料并爬取
  • 統計京東上不同手機品牌的評價量并以條形圖形式展示

爬取淘寶資料

  • URL

    電腦浏覽器打開淘寶,搜尋手機,得到浏覽器位址欄連結為https://s.taobao.com/search?ie=utf8&initiative_id=staobaoz_20170905&stats_click=search_radio_all%3A1&js=1&imgfile=&q=%E6%89%8B%E6%9C%BA&suggest=0_1&_input_charset=utf-8&wq=u&suggest_query=u&source=suggest&p4ppushleft=5%2C48&s=48

    經過測試,發現q=之後為關鍵詞手機,s=之後為頁數乘以48,48為每頁顯示的商品數量。是以寫得URL函數如下:

def key_name( number ):
    #擷取頁面的内容并傳回
    name = '手機'
    URL_1 = "https://s.taobao.com/search?ie=utf8&initiative_id=staobaoz_20170905&stats_click=search_radio_all%3A1&js=1&imgfile=&q="
    URL_2 = "&suggest=0_1&_input_charset=utf-8&wq=u&suggest_query=u&source=suggest&p4ppushleft=5%2C48&s="
    URL = ( URL_1 + name + URL_2 + str(number))
    #print(URL)
    res = requests.get( URL )
    return res.text
           
  • 擷取資料塊

    檢視淘寶搜尋手機後所在頁面源代碼如圖

    用python買手機用python買手機
    可以看到,我所需要的手機價格與月銷量等資料在data:之後,header之前,是以使用正規表達式來擷取資料塊,擷取資料塊代碼如下:
def find_date( text):
    #根據整個頁面的資訊,擷取商品的資料所在的HTML源碼并放回
    reg = r',"data":{"spus":\[({.+?)\]}},"header":'
    reg = re.compile(reg)
    info = re.findall(reg, text)
    return info[0]
           
  • 解析資料

    擷取到資料塊之後,需要從資料塊中解析需要的手機品牌、配置、價格、月銷量等資料。需要注意的是,代碼擷取的價格和月銷量為字元串形式,需要強制轉換為int型再寫入excel表格。

    對于計算不同品牌手機的月銷量問題,采用字元串查找方式,比如華為手機,在手機商品的标題中查找‘華為’、‘榮耀’關鍵詞,如查找到,則該手機則認為是華為手機,月銷量加在華為手機上。

    代碼如下:

def manipulation_data( info, sales_count, sheet ):
    #解析擷取的HTML源碼,擷取資料
    Date = eval(info)

    for d in Date:
        T = " ".join([t['tag'] for t in d['tag_info']])
        #print(d['title'] + '\t' + d['price'] + '\t' + d['importantKey'][0:len(d['importantKey'])-1] + '\t' + T)
        #将資料寫入對應的excel表格中
        sheet.write(sales_count['line'],0,d['title'])
        sheet.write(sales_count['line'],1,int(d['price']))
        sheet.write(sales_count['line'],2,int(d['month_sales']))
        sheet.write(sales_count['line'],3,T)
        #統計不同品牌手機的月銷售量
        for key in sales_count.keys():
            if str(d['title']).find('榮耀')>=0:
                sales_count['華為']=sales_count['華為']+(int(d['month_sales']))
            elif str(d['title']).find(str(key))>=0:
                sales_count[key]=sales_count[key]+(int(d['month_sales']))
        sales_count['line']= sales_count['line'] + 1
    return sales_count
           
  • 繪制條形圖

    得到不同品牌手機月銷量後,需要對其進行按月銷量進行排序,使用sorted方法,排序完成後再使用dict方法強制轉換為字典形式,我寫了兩個繪制條形圖函數,可根據需要調用,使用包主要是matplotlib和pygal:

def show(sales_count):
    #按照手機銷售量進行排序并繪圖(網頁版)
    sales_count=dict(sorted(sales_count.items(),key=lambda d:d[1],reverse=True))
    print('正在繪制直方圖')
    picture=pygal.Bar()
    picture.title="各大品牌手機月銷售量直方圖   by社會主義接班人1号"
    picture.x_labels=sales_count.keys()
    sales_count.keys()
    picture.x_title="手機品牌"
    picture.y_title="月銷售量"
    picture.add('淘寶',sales_count.values())
    picture.render_to_file('淘寶手機月銷售量直方圖.svg')
    print('繪制完成')
    print(sales_count)

def show2(sales_count):
    #按照手機銷售量進行排序并繪圖(圖檔版)
    sales_count=dict(sorted(sales_count.items(),key=lambda d:d[1],reverse=True))
    print('正在繪制直方圖')
    x=[0,1,2,3,4,5,6,7,8,9,10]
    picture=plt.bar(x,sales_count.values(),width=0.4,tick_label=list(sales_count.keys()),fc='r')
    for rect in picture:
        h=rect.get_height()
        plt.text(rect.get_x()+rect.get_width()-0.6,1.03*h,'%d'% int(h))
    plt.xlabel('手機品牌')
    plt.ylabel('月銷售量')
    plt.title('各大品牌手機月銷售量直方圖   by社會主義接班人1号')
    plt.savefig("淘寶手機月銷售量直方圖.jpg")
    print('繪制完成')
    plt.show()
    print(sales_count)
    
           
  • 主函數

    主函數如下:

def main():
    #初始化建立字典,key為手機品牌,value為月銷量
    sales_count={'華為':0,'小米':0,'蘋果':0,'vivo':0,'OPPO':0,'魅族':0,'紐曼':0,'尼凱恩':0,'諾基亞':0,'三星':0,'聯想':0,'line':1}
    book = Workbook()
    #建立excel表格
    sheet = book.add_sheet('淘寶手機資料')
    sheet.write(0,0,'品牌')
    sheet.write(0,1,'價格')
    sheet.write(0,2,'月銷售量')
    sheet.write(0,3,'配置')
    book.save('淘寶手機資料.xls')
    #k用于生成連結,每個連結的最後面的數字相差48.
    #sales_count['line']用于記錄表格的資料行數,便于寫入資料
    #end為結束頁數,可通過end控制擷取資料數量
    k = 0
    end=20
    for i in range(end+1):
        text = key_name( k + i * 48 )
        info = find_date(text)
        sales_count= manipulation_data( info ,sales_count, sheet )
    
        book.save('淘寶手機資料.xls')
        print('爬取第' + str(i) + '頁資料完成,共'+str(end)+'頁')
    del sales_count['line']
    #show(sales_count)
    show2(sales_count)
           
  • 運作結果
    用python買手機用python買手機
    用python買手機用python買手機
    用python買手機用python買手機

爬取京東資料

京東的情況與淘寶略有不同,京東是搜尋一頁商品後,滑鼠下滑加載下一頁,是以需要用到webdriver模拟浏覽器打開滑鼠下滑操作,并且京東資料塊也與淘寶有所不同。并且京東并沒有月銷量,隻有評價人數。不同代碼如下:

def key_name( driver,number ):
    #擷取頁面的内容并傳回
    name = '手機'
    URL_1 = "https://search.jd.com/Search?keyword="
    URL_2 = "&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq="
    URL_3="&cid2=653&cid3=655&page="
    URL_4 = "&s=1&click=0"
    URL = ( URL_1 + name + URL_2 + name + URL_3+ str(number)+URL_4)
    #driver = webdriver.Firefox()
    #driver.implicitly_wait(3)
    driver.get(URL)

    # 模拟下滑到底部操作
    for i in range(1, 5):
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(1)

    # 将加載好的頁面源碼給bs4解析
    soup = BeautifulSoup(driver.page_source, "html.parser")
    t=0

    # 進行資訊的抽取(商品名稱,價格)
    goods_info = soup.select(".gl-item")
    #driver.close()
    return goods_info



def manipulation_data( goods_info, sales_count, sheet ):
    #解析擷取的HTML源碼,擷取資料并對資料進行解析
    for info in goods_info:
        title = info.select(".p-name.p-name-type-2 a")[0].text.strip()
        price_str = info.select(".p-price")[0].text.strip()
        count_str = info.select(".p-commit")[0].text.strip()
        #print (title)
        price_start=price_str.find('¥')+1
        price_end=price_str.find('.')
        price=int(price_str[price_start:price_end])
        #print (price)
        if(count_str.find('\n'))>=0:
            count_start=count_str.find('\n')+1
        else:
            count_start=0
        if(count_str.find('萬+'))>=0:
            count=float(count_str[count_start:count_str.find('萬')])*10000
        elif(count_str.find('+'))>=0:
            count=int(count_str[count_start:count_str.find('+')])
        #print(count)
        sheet.write(sales_count['line'],0,title)
        sheet.write(sales_count['line'],1,int(price))
        sheet.write(sales_count['line'],2,int(count))
        for key in sales_count.keys():
            if str(title).find('榮耀')>=0:
                sales_count['華為']=sales_count['華為']+(int(count))
            elif str(title).find('Apple')>=0:
                sales_count['蘋果']=sales_count['蘋果']+(int(count))
            elif str(title).find(str(key))>=0:
                sales_count[key]=sales_count[key]+(int(count))
        sales_count['line']= sales_count['line'] + 1
    return sales_count



def main():
    sales_count={'華為':0,'小米':0,'蘋果':0,'vivo':0,'OPPO':0,'魅族':0,'紐曼':0,'尼凱恩':0,'諾基亞':0,'三星':0,'聯想':0,'line':1}
    book = Workbook()
    sheet = book.add_sheet('京東手機資料')
    sheet.write(0,0,'手機')
    sheet.write(0,1,'價格')
    sheet.write(0,2,'評價數量')
    book.save('京東手機資料.xls')
    driver = webdriver.Firefox()
    driver.implicitly_wait(3)
    end=30
    #sales_count['line']用于記錄表格的資料行數,便于寫入資料  
    for i in range(end):
        goods_info = key_name(driver,i*2)
        sales_count= manipulation_data( goods_info ,sales_count, sheet )    
        book.save('京東手機資料.xls')
        print('爬取第' + str(i+1) + '頁資料完成,共'+str(end)+'頁')
    del sales_count['line']
    #show(sales_count)
    show2(sales_count)
           
  • 運作結果
    用python買手機用python買手機
    用python買手機用python買手機
    用python買手機用python買手機
    對比淘寶和京東資料發現,淘寶上華為一馬當先,京東上幾乎是華為、蘋果各占半壁江山,都說華為賺錢,這次我信了。

本文完

1

  1. 部分代碼來源網絡,如有侵權,請聯系 ↩︎