首頁 > 軟體

基於Python獲取亞馬遜的評論資訊的處理

2022-02-19 10:00:02

上次亞馬遜的商品資訊都獲取到了,自然要看一下評論的部分。使用者的評論能直觀的反映當前商品值不值得購買,亞馬遜的評分資訊也能獲取到做一個評分的權重。

亞馬遜的評論區由使用者ID,評分及評論標題,地區時間,評論正文這幾個部分組成,本次獲取的內容就是這些。

測試連結: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

一、分析亞馬遜的評論請求

首先開啟開發者模式的Network,Clear清屏做一次請求:

你會發現在Doc中的get請求正好就有我們想要的評論資訊。

可是真正的評論資料可不是全部都在這裡的,頁面往下翻,有個翻頁的button:

點選翻頁請求下一頁,在Fetch/XHR索引標籤中多了一個新的請求,剛才的Doc索引標籤中並無新的get請求。這下發現了所有的評論資訊是XHR型別的請求。

獲取到post請求的連結和payload資料,裡面含有控制翻頁的引數,真正的評論請求已經找到了。

這一堆就是未處理的資訊,這些請求未處理的資訊裡面,帶有data-hook="review"的就是帶有評論的資訊。分析完畢,下面開始一步一步去寫請求。

二、獲取亞馬遜評論的內容

首先拼湊請求所需的post引數,請求連結,以便之後的自動翻頁,然後帶引數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",
}
# 翻頁關鍵payload引數賦值
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)

現在已經獲取到了這一堆未處理的資訊,接下來開始對這些資料進行處理。

三、亞馬遜評論資訊的處理

上圖的資訊會發現,每一段的資訊都由“&&&”進行分隔,而分隔之後的每一條資訊都是由'","'分隔開的:

所以用python的split方法進行處理,把字串分隔成list列表:

# 返回值字串處理
contents = res.split('&&&')
for content in contents:
    infos = content.split('","')

由'","'分隔的資料通過split處理生成新的list列表,評論內容是列表的最後一個元素,去掉裡面的"","n"和多餘的符號,就可以通過css/xpath選擇其進行處理了:

for content in contents:
    infos = content.split('","')
    info = infos[-1].replace('"]','').replace('\n','').replace('\','')
    # 評論內容判斷
    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() #評價標題
        data['detail'] = sel.xpath('//span[@data-hook="review-body"]').extract_first() #評價內容
        image = sel.xpath('div[@class="review-image-tile-section"]').extract_first()
        data['image'] = image if image else "not image" #圖片
        print(data)

四、程式碼整合

4.1 代理設定

穩定的IP代理是你資料獲取最有力的工具。目前國內還是無法穩定的存取亞馬遜,會出現連線失敗的情況。我這裡使用的ipidea代理請求的義大利地區的亞馬遜,可以通過賬密和api獲取代理,速度還是非常穩定的。

地址: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迴圈翻頁

while迴圈進行翻頁,評論最大頁數是99頁,99頁之後就break跳出while迴圈:

 def getPLPage(self):
        while True:
            # 翻頁關鍵payload引數賦值
            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('\','')
                    # 評論內容判斷
                    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() #評價標題
                        data['detail'] = sel.xpath('//span[@data-hook="review-body"]').extract_first() #評價內容
                        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引數目前寫死在
    #"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:
            # 翻頁關鍵payload引數賦值
            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('\','')
                    # 評論內容判斷
                    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() #評價標題
                        data['detail'] = sel.xpath('//span[@data-hook="review-body"]').extract_first() #評價內容
                        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('獲取失敗')
    #專門傳送請求的方法,代理請求三次,三次失敗返回錯誤
    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()

總結

本次的亞馬遜評論獲取就是兩個坑,一是評論資訊通過的XHR請求方式,二是評論資訊的處理。分析之後這次的資料獲取還是非常簡單的,找到正確的請求方式,穩定的IP代理讓你事半功倍,找到資訊的共同點進行處理,問題就迎刃而解了。

到此這篇關於基於Python獲取亞馬遜的評論的文章就介紹到這了,更多相關Python亞馬遜的評論內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com