码迷,mamicode.com
首页 > 编程语言 > 详细

[python]利用selenium模拟用户操作抓取天猫评论数据

时间:2017-08-16 18:25:19      阅读:347      评论:0      收藏:0      [点我收藏+]

标签:指定元素   nal   pre   cmd   name   标记   selector   webdriver   文件夹权限   

准备:

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模拟用户操作抓取天猫评论数据 - 知乎专栏

Python爬虫利器五之Selenium的用法 | 静觅

Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺 | 静觅

通过Python抓取天猫评论数据

Python Package Index

[python]利用selenium模拟用户操作抓取天猫评论数据

标签:指定元素   nal   pre   cmd   name   标记   selector   webdriver   文件夹权限   

原文地址:http://www.cnblogs.com/yowamushi/p/7374216.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!