前期出了一個《爬取京東商品評價信息實戰》的教程,最近又有網友提到要出一個爬淘寶商品評論的教程。說實話淘寶的反爬機制做得比京東要嚴,所以用爬取京東商品評價信息的方式取爬取淘寶商品評價不太可行。本文還是介紹通過Selenium模擬登錄後來進行淘寶商品評價信息的爬取。
Selenium安裝與配置及如何模擬登錄淘寶見《Selenium安裝與配置》及《Selenium實戰-模擬登錄淘寶並爬取商品信息》
一、分析需要爬取的頁面
淘寶的商品評價信息在商品詳情頁面,需要登錄淘寶後,訪問到商品詳情頁,並且需要點擊“寶貝評價”才能看到相應的商品評價信息。
我們還是要通過chrome瀏覽器的調試模式來分析需要點擊哪個頁面元素才能看到具體的評價信息。通過分析可以得知要點擊<div class="Tabs--title--1Ov7S5f Tabs--active--2TTlc9s"><span data-spm-anchor-id="pc_detail.27183998/evo365560b447259.202205.i0.65b87dd6RabS41">寶貝評價</span><div class="Tabs--line--1ibdRMv"></div></div>
這個元素才能進行切換到寶貝評價。
具體的評價信息是在<div class="Comment--content--15w7fKj" data-spm-anchor-id="pc_detail.27183998/evo365560b447259.202207.i0.65b87dd6RabS41">很好很喜歡下次還會買的,之前在這店買過iPhone12 Air pos pro iPad Air3 距離上個平板時隔三年又買了iPad Air5 物流也很快,唯一的不足就是要花我自己的錢買😂哈哈哈非常推薦 </div>
這些<div class="Comment--content--15w7fKj">......</div>
元素裏。
分析完頁面後,就可以開始思考如何編碼了。
二、實現爬取商品評價信息的代碼
通過上面的分析,我們要獲取商品評價信息,需要讓Selenium進行模擬登錄->訪問商品列表頁面->訪問商品詳情頁面->點擊“寶貝評價”->獲取並解析商品評價信息。
前面讓Selenium進行模擬登錄->訪問商品列表頁面在《Selenium實戰-模擬登錄淘寶並爬取商品信息》已有介紹。這裏主要介紹後面的部分,訪問商品詳情頁面->點擊“寶貝評價”->獲取並解析商品評價信息。
獲取並解析商品評價信息有兩種方式,一種是通過解析顯示評價信息的元素獲取,一種是通過mitmproxy代理進行流量抓包獲取。
1、通過解析顯示評價信息的元素獲取商品評價信息
selenium_taobao.py的部分代碼參考如下:
# 解析獲取商品信息
def get_products():
"""提取商品數據"""
html = driver.page_source
doc = pq(html)
items = doc('.Card--doubleCardWrapper--L2XFE73').items()
for item in items:
product = {'url': item.attr('href'),
'price': item.find('.Price--priceInt--ZlsSi_M').text(),
'realsales': item.find('.Price--realSales--FhTZc7U-cnt').text(),
'title': item.find('.Title--title--jCOPvpf').text(),
'shop': item.find('.ShopInfo--TextAndPic--yH0AZfx').text(),
'location': item.find('.Price--procity--_7Vt3mX').text()}
print(product)
item_href=item.attr('href') # 得到商品的詳情訪問頁面
if item_href.find('https:')>=0:
item_url =item_href
print(item_url)
else:
item_url = "https:" + item.attr('href')
# 爬取商品評價
get_prod_comments(item_url)
time.sleep(sleeptime)
# 爬取商品評價
def get_prod_comments(item_url):
driver.get(item_url)
print('跳轉至詳情頁.......'+item_url)
ele = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@class='Tabs--title--1Ov7S5f ']/span")))
time.sleep(sleeptime)
# 向下滾動至目標元素可見
js = "arguments[0].scrollIntoView();"
driver.execute_script(js, ele)
print('向下滾動至-寶貝評價-元素可見.......')
driver.execute_script("arguments[0].click();", ele)
print('點擊-寶貝評價.......')
ele_comments=driver.find_elements(By.CSS_SELECTOR,".Comment--content--15w7fKj")
print('提取寶貝評價信息.......')
for ele_comment in ele_comments:
print(ele_comment.text)
在解析獲取商品信息的方法中通過item_href=item.attr(‘href’) # 得到商品的詳情訪問頁面
在爬取商品評價get_prod_comments(item_url)的方法中,通過driver.get(item_url)跳轉到了商品詳情頁面。通過ele = wait.until(EC.element_to_be_clickable((By.XPATH, “//div[@class='Tabs–title–1Ov7S5f ']/span”)))定位到“寶貝評價”的點擊按鈕,通過driver.execute_script(“arguments[0].click();”, ele)進行點擊事件,然後通過ele_comments=driver.find_elements(By.CSS_SELECTOR,“.Comment–content–15w7fKj”)找到顯示評價信息的元素,循環後解析具體的評價文本信息。
效果如下:
2、通過mitmproxy代理進行流量抓包獲取商品評價信息
既然通過Selenium進行模擬點擊“寶貝評價”訪問了商品評價信息,也可通過流量抓包的方式來獲取商品評價信息。
同樣chrome瀏覽器的調試模式來分析商品評價是從哪些接口返回的數據,這裏可以看到寶貝評價是通過https://h5api.m.taobao.com/h5/mtop.alibaba.review.list.for.new.pc.detail/1.0/....
接口返回的數據。
切換到Response,可以看到接口返回的寶貝評價JSON串。
有了這些信息後,就可以寫mitmproxy代理抓包的代碼了。
taobao_scripts.py代碼如下:
import json
# 抓取淘寶商品評價信息
def response(flow):
url = 'https://h5api.m.taobao.com/h5/mtop.alibaba.review.list.for.new.pc.detail'
if flow.request.url.startswith(url):
text = flow.response.text
json_data = json.loads(text)
print(json_data)
在控制檯運行 mitmdump -s taobao_scripts.py 啓動mitmproxy代理服務。具體參考《Selenium實戰-模擬登錄淘寶並爬取商品信息》設置好chrome瀏覽器的mitmproxy代理。然後運行selenium_taobao.py通過Selenium驅動瀏覽器,進行自動模擬登錄->訪問商品列表頁面->訪問商品詳情頁面->點擊“寶貝評價”。
在運行mitmdump的控制檯可以看到通過抓包獲取的淘寶商品評價的數據信息。
效果如下圖:
三、附-完整代碼
selenium_taobao.py完整代碼如下
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common import TimeoutException, NoSuchElementException
from urllib.parse import quote
from pyquery import PyQuery as pq
import time
sleeptime=5
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "localhost:9222") #此處端口保持和命令行啓動的端口一致
driver = Chrome(options=chrome_options)
driver.implicitly_wait(5) # 隱式等待
wait = WebDriverWait(driver, 10) # 顯示等待
# 模擬淘寶登錄
def login_taobao():
print('開始登錄...')
try:
login_url='https://login.taobao.com/member/login.jhtml'
driver.get(login_url)
check_login_type()
input_login_id = wait.until(EC.presence_of_element_located((By.ID, 'fm-login-id')))
input_login_password = wait.until(EC.presence_of_element_located((By.ID, 'fm-login-password')))
input_login_id.send_keys('your account')
input_login_password.send_keys('your password')
submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.fm-button.fm-submit.password-login')))
submit.click()
is_loging = wait.until(EC.url_changes(login_url))
return is_loging
except TimeoutException:
print('login_taobao TimeoutException')
submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.fm-button.fm-submit')))
submit.click()
is_loging = wait.until(EC.url_changes(login_url))
if is_loging:
return is_loging
else:
login_taobao()
# 判斷登錄模式,如果是掃描登錄則切換到用戶名密碼登錄模式
def check_login_type():
print('判斷登錄模式')
try:
wait.until(EC.presence_of_element_located((By.ID, 'fm-login-id')))
except TimeoutException:
change_type = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.iconfont.icon-password')))
change_type.click() # 切換到用戶密碼模式登錄
print('切換到用戶密碼模式登錄...')
# 解析獲取商品信息
def get_products():
"""提取商品數據"""
html = driver.page_source
doc = pq(html)
items = doc('.Card--doubleCardWrapper--L2XFE73').items()
for item in items:
product = {'url': item.attr('href'),
'price': item.find('.Price--priceInt--ZlsSi_M').text(),
'realsales': item.find('.Price--realSales--FhTZc7U-cnt').text(),
'title': item.find('.Title--title--jCOPvpf').text(),
'shop': item.find('.ShopInfo--TextAndPic--yH0AZfx').text(),
'location': item.find('.Price--procity--_7Vt3mX').text()}
print(product)
item_href=item.attr('href') # 得到商品的詳情訪問頁面
if item_href.find('https:')>=0:
item_url =item_href
print(item_url)
else:
item_url = "https:" + item.attr('href')
# 爬取商品評價
get_prod_comments(item_url)
time.sleep(sleeptime)
# 爬取商品評價
def get_prod_comments(item_url):
driver.get(item_url)
print('跳轉至詳情頁.......'+item_url)
ele = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@class='Tabs--title--1Ov7S5f ']/span")))
time.sleep(sleeptime)
# 向下滾動至目標元素可見
js = "arguments[0].scrollIntoView();"
driver.execute_script(js, ele)
print('向下滾動至-寶貝評價-元素可見.......')
driver.execute_script("arguments[0].click();", ele)
print('點擊-寶貝評價.......')
ele_comments=driver.find_elements(By.CSS_SELECTOR,".Comment--content--15w7fKj")
print('提取寶貝評價信息.......')
for ele_comment in ele_comments:
print(ele_comment.text)
# 自動獲取商品信息並自動翻頁
def index_page(url,cur_page,max_page):
print(' 正在爬取:'+url)
try:
driver.get(url)
get_products()
next_page_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//button/span[contains(text(),"下一頁")]')))
next_page_btn.click()
do_change = wait.until(EC.url_changes(url))
if do_change and cur_page<max_page:
new_url=driver.current_url
cur_page = cur_page + 1
index_page(new_url,cur_page,max_page)
except TimeoutException:
print('---index_page TimeoutException---')
if __name__ == '__main__':
is_loging=login_taobao()
if is_loging:
print('已經登錄')
KEYWORD = 'iPad'
url = 'https://s.taobao.com/search?page=1&q=' + quote(KEYWORD) + '&tab=all'
max_page=1
index_page(url,1,max_page)