准備:
python3.5
安裝selenium包
第一種方法:
cmd里輸pip install selenium,但是經常報錯
第二種方法:
下載安裝包-cmd進入解壓路徑-python setup.py install-報錯permission denied-右鍵安全更改報錯文件夾權限為完全控制-再次安裝成功
unknown error: unable to discover open pages-下載chromedriver放在環境變量目錄下
測試自動打開百度時提示“您使用的是不受支持的命令行標記”-更改chromedriver版本為對應版本即可
安裝包下載地址:https://pypi.python.org/pypi/selenium
chromedriver與chrome版本映射及下載地址:http://blog.csdn.net/huilan_same/article/details/51896672
實現:
selenium基本上就是模擬打開瀏覽器,向下滑動點擊評論tab點擊下一頁等過程。由於selenium只能對顯示在屏幕范圍內的元素操作,所以滾動條操作很重要。
def deal_recommends_infos(url): if not url.startswith('http'): url = 'https:' + url print('開始尋找評論:' + url) driver = webdriver.Chrome() driver.maximize_window() # 全屏 timeout = 30 try: driver.get(url) WebDriverWait(driver, timeout).until( EC.presence_of_element_located((By.ID, "J_TabBarBox")) # 判斷頁面是否初步加載成功的標記 ) except TimeoutException: print('寶貝鏈接未加載成功') try: # 頁面上拉600,看到TabBarBox js = "window.scrollTo(0,600)" driver.execute_script(js) except WebDriverException: print('上拉尋找評論區時出現問題') time.sleep(2) # 點擊累計評論TAB driver.find_element_by_xpath('//*[@id="J_TabBar"]/li[2]').click() time.sleep(4) print('成功點擊累計評論TAB') try: # rate-grid的正則表達式 driver.find_element_by_xpath('//*[@id="J_Reviews"]/div/div[6]') except NoSuchElementException: print('評論信息中元素還未加載') print('已經成功加載到評論區信息') for i in range(2): try: js = "window.scrollTo(0,2500)" driver.execute_script(js) time.sleep(2) # 點擊下一頁 driver.find_element_by_css_selector('#J_Reviews > div > div.rate-page > div > a:last-child').click() except WebDriverException: js = "window.scrollTo(0,3500)" driver.execute_script(js) time.sleep(2) # 點擊下一頁 driver.find_element_by_css_selector('#J_Reviews > div > div.rate-page > div > a:last-child').click() except NoSuchElementException: print('找不到翻頁按鈕') continue print('已成功點擊下一頁') soup = BeautifulSoup(driver.page_source, "lxml") print(get_recommends_infos(soup)) print('完成該鏈接的評論抓取')
要注意的點:
瀏覽器要全屏,缺少這個操作的話很容易出現bug,我猜是因為天貓商城右下角的二維碼妨礙了鼠標點擊。
下拉網頁點擊下一頁時,由於天貓商城每頁的評論長度不是那么確定,設置絕對值容易出現拉不到或者拉過了的情況,要做一個try語句。
target = driver.find_element_by_css_selector('#J_Reviews > div > div.rate-page > div > a:last-child') driver.execute_script("arguments[0].scrollIntoView();",target) #拖動到可見的元素去
我嘗試用以上代碼來滾動到指定元素可見,但是總報is not clickable at point (1030, 19). Other element would receive the click:查了下是被天貓商城那個手機購買的二維碼擋住了……現在暫時沒有解決方案,只能先拉2500,不夠就再加個1000。
理論上來說
soup = BeautifulSoup(driver.page_source, "lxml") print(get_recommends_infos(soup))
這兩句應該是放在點擊下一頁之前的,但是不知道為啥這樣就會出現把第一頁抓取兩遍的情況。神tm換下代碼順序就正常了,想不通為什么這樣結果對,我再慢慢研究吧。
#提取評論信息 def get_recommends_infos(s): comment = s.find("div",class_="rate-grid") comment_data = comment.find_all("tr") lst1=[] #逐行讀取 for i in comment_data: goodstype_lst=[] username_lst=[] #comment1為初次評論,comment2為追加評論,reply1為商家初次回復,reply2為商家追加回復,goodstype為商品類型,username為用戶名 dic={'comment1': '','reply1':'','comment2': '','reply2':'', 'goodstype': goodstype_lst, 'username': username_lst} try: content1=i.find('div',class_="tm-rate-premiere").find('div',class_="tm-rate-content") dic['comment1']=content1.text except: content1=i.find('div',class_="tm-rate-content").find('div',class_="tm-rate-fulltxt") dic['comment1']=content1.text try: content2=i.find('div',class_="tm-rate-append").find('div',class_="tm-rate-content") dic['comment2']=content2.text except: dic['comment2']='null' try: reply1=i.find('div',class_="tm-rate-premiere").find('div',class_="tm-rate-reply") dic['reply1']=reply1.text except: try: reply2=i.find('div',class_="tm-rate-append").find('div',class_="tm-rate-reply") dic['reply1']='null' except: try: reply1=i.find('div',class_="tm-rate-reply") dic['reply1']=reply1.text except: dic['reply1']='null' try: reply2=i.find('div',class_="tm-rate-append").find('div',class_="tm-rate-reply") dic['reply2']=reply2.text except: dic['reply2']='null' goodstype=i.find('div',class_="rate-sku").find_all('p') for b in goodstype: goodstype_lst.append(b.attrs['title']) username=i.find_all('div',class_="rate-user-info") for c in username: username_lst.append(c.text) lst1.append(dic) return lst1
要注意的點:
初次評論:如果有追加評論的話div會被分成class=tm-rate-premiere和tm-rate-append兩塊,這兩塊里面又分別有tm-rate-content,沒有追加評論的情況下評論就是tm-rate-content一整塊。因此直接用BeautifulSoup找tm-rate-content是有問題的,可能會找到兩個評論。
追加評論:這個比較好判斷,沒有tm-rate-append的話就沒有追加評論
初次回復:回復情況分為下表6種,其中有初次回復的分為1、2、5共3種,先通過find('div',class_="tm-rate-premiere").find('div',class_="tm-rate-reply")把1選出來了,剩下5種中,把3排除掉,第一個被找到的tm-rate-reply就是初次回復。
| 序號 | 追評 | 初次回復 | 追評回復 |
| 1 | 有 | 有 | 有 |
| 2 | 有 | 有 | 無 |
| 3 | 有 | 無 | 有 |
| 4 | 有 | 無 | 無 |
| 5 | 無 | 有 | 無 |
| 6 | 無 | 無 | 無 |
追加回復:通過find('div',class_="tm-rate-append").find('div',class_="tm-rate-reply")把1、3選出來了,剩下的都為null
參考:
Python利器之使用Selenium模擬用戶操作抓取天貓評論數據 - 知乎專欄
