基于Python獲取亞馬遜的評論信息的處理
上次亞馬遜的商品信息都獲取到了,自然要看一下評論的部分。用戶的評論能直觀的反映當(dāng)前商品值不值得購買,亞馬遜的評分信息也能獲取到做一個評分的權(quán)重。
亞馬遜的評論區(qū)由用戶ID,評分及評論標(biāo)題,地區(qū)時間,評論正文這幾個部分組成,本次獲取的內(nèi)容就是這些。
測試鏈接:https://www.amazon.it/product-reviews/B08GHGTGQ2/ref=cm_cr_arp_d_paging_btm_14?ie=UTF8&pageNumber=14&reviewerType=all_reviews&pageSize=10&sortBy=recent
一、分析亞馬遜的評論請求
首先打開開發(fā)者模式的Network,Clear清屏做一次請求:
你會發(fā)現(xiàn)在Doc中的get請求正好就有我們想要的評論信息。
可是真正的評論數(shù)據(jù)可不是全部都在這里的,頁面往下翻,有個翻頁的button:
點擊翻頁請求下一頁,在Fetch/XHR選項卡中多了一個新的請求,剛才的Doc選項卡中并無新的get請求。這下發(fā)現(xiàn)了所有的評論信息是XHR類型的請求。
獲取到post請求的鏈接和payload數(shù)據(jù),里面含有控制翻頁的參數(shù),真正的評論請求已經(jīng)找到了。
這一堆就是未處理的信息,這些請求未處理的信息里面,帶有data-hook=\"review\"的就是帶有評論的信息。分析完畢,下面開始一步一步去寫請求。
二、獲取亞馬遜評論的內(nèi)容
首先拼湊請求所需的post參數(shù),請求鏈接,以便之后的自動翻頁,然后帶參數(shù)post請求鏈接:
headers = { 'authority': 'www.amazon.it', "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", } page = 1 post_data = { "sortBy": "recent", "reviewerType": "all_reviews", "formatType": "", "mediaType": "", "filterByStar": "", "filterByLanguage": "", "filterByKeyword": "", "shouldAppend": "undefined", "deviceType": "desktop", "canShowIntHeader": "undefined", "pageSize": "10", "asin": "B08GHGTGQ2", } # 翻頁關(guān)鍵payload參數(shù)賦值 post_data["pageNumber"] = page, post_data["reftag"] = f"cm_cr_getr_d_paging_btm_next_{page}", post_data["scope"] = f"reviewsAjax{page}", # 翻頁鏈接賦值 spiderurl=f'https://www.amazon.it/hz/reviewsrender/ajax/reviews/get/ref=cm_cr_getr_d_paging_btm_next_{page}' res = requests.post(spiderurl,headers=headers,data=post_data) if res and res.status_code == 200: res = res.content.decode('utf-8') print(res)
現(xiàn)在已經(jīng)獲取到了這一堆未處理的信息,接下來開始對這些數(shù)據(jù)進(jìn)行處理。
三、亞馬遜評論信息的處理
上圖的信息會發(fā)現(xiàn),每一段的信息都由“&&&”進(jìn)行分隔,而分隔之后的每一條信息都是由'","'分隔開的:
所以用python的split方法進(jìn)行處理,把字符串分隔成list列表:
# 返回值字符串處理 contents = res.split('&&&') for content in contents: infos = content.split('","')
由'","'分隔的數(shù)據(jù)通過split處理生成新的list列表,評論內(nèi)容是列表的最后一個元素,去掉里面的"\","\n"和多余的符號,就可以通過css/xpath選擇其進(jìn)行處理了:
for content in contents: infos = content.split('","') info = infos[-1].replace('"]','').replace('\\n','').replace('\\','') # 評論內(nèi)容判斷 if 'data-hook="review"' in info: sel = Selector(text=info) data = {} data['username'] = sel.xpath('//span[@class="a-profile-name"]/text()').extract_first() #用戶名 data['point'] = sel.xpath('//span[@class="a-icon-alt"]/text()').extract_first() #評分 data['date'] = sel.xpath('//span[@data-hook="review-date"]/text()').extract_first() #日期地址 data['review'] = sel.xpath('//span[@data-hook="review-title"]/span/text()').extract_first() #評價標(biāo)題 data['detail'] = sel.xpath('//span[@data-hook="review-body"]').extract_first() #評價內(nèi)容 image = sel.xpath('div[@class="review-image-tile-section"]').extract_first() data['image'] = image if image else "not image" #圖片 print(data)
四、代碼整合
4.1 代理設(shè)置
穩(wěn)定的IP代理是你數(shù)據(jù)獲取最有力的工具。目前國內(nèi)還是無法穩(wěn)定的訪問亞馬遜,會出現(xiàn)連接失敗的情況。我這里使用的ipidea代理請求的意大利地區(qū)的亞馬遜,可以通過賬密和api獲取代理,速度還是非常穩(wěn)定的。
地址:http://www.ipidea.net/?utm-source=csdn&utm-keyword=?wb
下面的代理獲取的方法:
# api獲取ip def getApiIp(self): # 獲取且僅獲取一個ip------意大利 api_url = '獲取代理地址' res = requests.get(api_url, timeout=5) try: if res.status_code == 200: api_data = res.json()['data'][0] proxies = { 'http': 'http://{}:{}'.format(api_data['ip'], api_data['port']), 'https': 'http://{}:{}'.format(api_data['ip'], api_data['port']), } print(proxies) return proxies else: print('獲取失敗') except: print('獲取失敗')
4.2 while循環(huán)翻頁
while循環(huán)進(jìn)行翻頁,評論最大頁數(shù)是99頁,99頁之后就break跳出while循環(huán):
def getPLPage(self): while True: # 翻頁關(guān)鍵payload參數(shù)賦值 self.post_data["pageNumber"]= self.page, self.post_data["reftag"] = f"cm_cr_getr_d_paging_btm_next_{self.page}", self.post_data["scope"] = f"reviewsAjax{self.page}", # 翻頁鏈接賦值 spiderurl = f'https://www.amazon.it/hz/reviews-render/ajax/reviews/get/ref=cm_cr_getr_d_paging_btm_next_{self.page}' res = self.getRes(spiderurl,self.headers,'',self.post_data,'POST',check)#自己封裝的請求方法 if res: res = res.content.decode('utf-8') # 返回值字符串處理 contents = res.split('&&&') for content in contents: infos = content.split('","') info = infos[-1].replace('"]','').replace('\\n','').replace('\\','') # 評論內(nèi)容判斷 if 'data-hook="review"' in info: sel = Selector(text=info) data = {} data['username'] = sel.xpath('//span[@class="a-profile-name"]/text()').extract_first() #用戶名 data['point'] = sel.xpath('//span[@class="a-icon-alt"]/text()').extract_first() #評分 data['date'] = sel.xpath('//span[@data-hook="review-date"]/text()').extract_first() #日期地址 data['review'] = sel.xpath('//span[@data-hook="review-title"]/span/text()').extract_first() #評價標(biāo)題 data['detail'] = sel.xpath('//span[@data-hook="review-body"]').extract_first() #評價內(nèi)容 image = sel.xpath('div[@class="review-image-tile-section"]').extract_first() data['image'] = image if image else "not image" #圖片 print(data) if self.page <= 99: print('Next Page') self.page += 1 else: break
最后的整合代碼:
# coding=utf-8 import requests from scrapy import Selector class getReview(): page = 1 headers = { 'authority': 'www.amazon.it', "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", } post_data = { "sortBy": "recent", "reviewerType": "all_reviews", "formatType": "", "mediaType": "", "filterByStar": "", "filterByLanguage": "", "filterByKeyword": "", "shouldAppend": "undefined", "deviceType": "desktop", "canShowIntHeader": "undefined", "pageSize": "10", "asin": "B08GHGTGQ2", #post_data中asin參數(shù)目前寫死在 #"https://www.amazon.it/product-reviews/B08GHGTGQ2?ie=UTF8&pageNumber=1&reviewerType=all_reviews&pageSize=10&sortBy=recent" #這個鏈接里,不排除asin值變化的可能,如要獲取get請求即可 def getPLPage(self): while True: # 翻頁關(guān)鍵payload參數(shù)賦值 self.post_data["pageNumber"]= self.page, self.post_data["reftag"] = f"cm_cr_getr_d_paging_btm_next_{self.page}", self.post_data["scope"] = f"reviewsAjax{self.page}", # 翻頁鏈接賦值 spiderurl = f'https://www.amazon.it/hz/reviews-render/ajax/reviews/get/ref=cm_cr_getr_d_paging_btm_next_{self.page}' res = self.getRes(spiderurl,self.headers,'',self.post_data,'POST',check)#自己封裝的請求方法 if res: res = res.content.decode('utf-8') # 返回值字符串處理 contents = res.split('&&&') for content in contents: infos = content.split('","') info = infos[-1].replace('"]','').replace('\\n','').replace('\\','') # 評論內(nèi)容判斷 if 'data-hook="review"' in info: sel = Selector(text=info) data = {} data['username'] = sel.xpath('//span[@class="a-profile-name"]/text()').extract_first() #用戶名 data['point'] = sel.xpath('//span[@class="a-icon-alt"]/text()').extract_first() #評分 data['date'] = sel.xpath('//span[@data-hook="review-date"]/text()').extract_first() #日期地址 data['review'] = sel.xpath('//span[@data-hook="review-title"]/span/text()').extract_first() #評價標(biāo)題 data['detail'] = sel.xpath('//span[@data-hook="review-body"]').extract_first() #評價內(nèi)容 image = sel.xpath('div[@class="review-image-tile-section"]').extract_first() data['image'] = image if image else "not image" #圖片 print(data) if self.page <= 99: print('Next Page') self.page += 1 else: break # api獲取ip def getApiIp(self): # 獲取且僅獲取一個ip------意大利 api_url = '獲取代理地址' res = requests.get(api_url, timeout=5) try: if res.status_code == 200: api_data = res.json()['data'][0] proxies = { 'http': 'http://{}:{}'.format(api_data['ip'], api_data['port']), 'https': 'http://{}:{}'.format(api_data['ip'], api_data['port']), } print(proxies) return proxies print('獲取失敗') except: print('獲取失敗') #專門發(fā)送請求的方法,代理請求三次,三次失敗返回錯誤 def getRes(self,url,headers,proxies,post_data,method): if proxies: for i in range(3): try: # 傳代理的post請求 if method == 'POST': res = requests.post(url,headers=headers,data=post_data,proxies=proxies) # 傳代理的get請求 else: res = requests.get(url, headers=headers,proxies=proxies) if res: return res except: print(f'第{i+1}次請求出錯') else: return None else: proxies = self.getApiIp() # 請求代理的post請求 res = requests.post(url, headers=headers, data=post_data, proxies=proxies) # 請求代理的get請求 res = requests.get(url, headers=headers, proxies=proxies) print(f"第{i+1}次請求出錯") if __name__ == '__main__': getReview().getPLPage()
總結(jié)
本次的亞馬遜評論獲取就是兩個坑,一是評論信息通過的XHR請求方式,二是評論信息的處理。分析之后這次的數(shù)據(jù)獲取還是非常簡單的,找到正確的請求方式,穩(wěn)定的IP代理讓你事半功倍,找到信息的共同點進(jìn)行處理,問題就迎刃而解了。
到此這篇關(guān)于基于Python獲取亞馬遜的評論的文章就介紹到這了,更多相關(guān)Python亞馬遜的評論內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何優(yōu)雅地改進(jìn)Django中的模板碎片緩存詳解
這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅地改進(jìn)Django中的模板碎片緩存的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07Django Rest Framework框架構(gòu)建復(fù)雜API技能詳解
這篇文章會詳細(xì)介紹Django REST Framework的核心組成部分,包括Serializers、ViewSets、Routers、權(quán)限和認(rèn)證系統(tǒng)以及測試和調(diào)試工具,文章從基礎(chǔ)開始,逐步深入,旨在幫助讀者掌握使用Django REST Framework構(gòu)建復(fù)雜API的技能2023-09-09python標(biāo)準(zhǔn)庫學(xué)習(xí)之sys模塊詳解
sys模塊是最常用的和python解釋器交互的模塊,sys模塊可供訪問由解釋器(interpreter)使用或維護(hù)的變量和與解釋器進(jìn)行交互的函數(shù),下面這篇文章主要給大家介紹了關(guān)于python標(biāo)準(zhǔn)庫學(xué)習(xí)之sys模塊的相關(guān)資料,需要的朋友可以參考下2022-08-08使用Python實現(xiàn)企業(yè)微信的自動打卡功能
下面就通過Python程序來實現(xiàn)自動打卡,原理很簡單,用Python設(shè)置定時任務(wù),然后通過adb操作手機(jī),完成打卡功能,感興趣的朋友跟隨小編一起看看吧2019-04-04