美文网首页我爱编程
Python爬虫:动态爬取QQ说说并生成词云,分析朋友状况

Python爬虫:动态爬取QQ说说并生成词云,分析朋友状况

作者: 部落大圣 | 来源:发表于2018-05-20 13:19 被阅读205次

    跟着@逆水寒大佬学爬虫,Python动态爬取QQ空间说说,把内容存入txt文档,然后将内容生成词云图。可以清晰看出朋友状况。

    1、爬取动态内容

    1、因为动态页面内容是动态加载的,我们需要不断下滑,加载页面。
    2、切换到当前内容的<frame>中,也可能不是<frame>,这里需要查看具体情况。
    3、获取页面数据,然后放在xpath中,然后读取。

    # 下拉滚动条,使浏览器加载出动态加载的内容,
          # 从1开始加载到6结束,分5次加载完每页数据   
        for i in range(1, 6):
             height = 20000*i  # 每次滑动20000像素
            strWrod = "windows.scrollBy(0, "+str(height)+")" # 制定滚动的像素数
      # 多数情况下一个网页由多个<frame>或<iframe>组成,webdrive默认定位的是最外层的<frame>,
     # 所以这时候要选中说说所在的<frame>,否则找不到下面需要的网页元素。
        driver.switch_to.frame("app_canvas_frame")
        selector = etree.HTML(driver.page_source)
        divs = select.xpath('//*[@id="msgList"]/li[1]/div[3]/div[2]')
    

    这里用到了Window scrollBy() 方法,滚动页面,scrollBy() 方法可把内容滚动指定的像素数。
    注意: 要使此方法工作 window 滚动条的可见属性必须设置为true!
    结合昨天学习的selenium模拟登陆知乎。开始今天的实战
    爬完完整代码如下:

    import time
    from selenium import webdriver
    from lxml import etree
    
    friend = '5XXXXX3'  # 朋友的QQ号,朋友的空间要求允许你能访问
    user = '2XXXXXXX'  # 你的QQ号
    pw = 'XXXXXXX'  # 你的QQ密码
    
    # 获取浏览器驱动
    driver = webdriver.Firefox()
    
    # 浏览器窗口最大化
    driver.maximize_window()
    
    # 浏览器地址定向为QQ登陆页面
    driver.get("http://i.qq.com")
    
    # 所以这里需要选中一下frame, 否则找不到下面需要的网页元素
    driver.switch_to.frame("login_frame")
    
    # 自动点击账号登陆方式
    driver.find_element_by_id("switcher_plogin").click()
    
    # 账号输入框输入已知QQ号
    driver.find_element_by_id("u").send_keys(user)
    
    # 密码框输入已知密码
    driver.find_element_by_id("p").send_keys(pw)
    
    # 自动点击登陆按钮
    driver.find_element_by_id("login_button").click()
    
    # 让webdriver操纵当前页
    driver.switch_to.default_content()
    time.sleep(4)
    # 跳到说说的url,friend你可以任意改成你想访问的空间
    driver.get("http://user.qzone.qq.com/"+friend+"/311")
    
    next_num = 0  # 初始“下一页”的id
    while True:
    
        # 下拉滚动条,使浏览器加载出动态加载的内容,
        # 我这里是从1开始到6结束 分5次加载每页数据
        for i in range(1, 6):
            height = 20000*i  # 每次滑动20000像素
            strWord = "window.scrollBy(0, "+str(height)+")"  # 按照指定像素滚动
            driver.execute_script(strWord)  # 执行Js脚本
            time.sleep(4)
    
        # 很多时候网页由多个<frame>或<iframe>组成,webdriver默认定位的是最外层的<frame>
        # 所以这里需要选中一下说说所在的<frame>,否则找不到下面需要的网页元素
        driver.switch_to.frame("app_canvas_frame")  # 定位<iframe>
        selector = etree.HTML(driver.page_source)  # 将当前网页解析成xpath
        divs = selector.xpath('//*[@id="msgList"]/li/div[3]')
        time.sleep(4)
    
        # 这里使用a表示内容可以连续不清空写入
        with open('qq_word.txt', 'a', encoding='utf-8')as f:
            for div in divs:
                qq_name = div.xpath('./div[2]/a/text()')  # 朋友名字
                qq_content = div.xpath('./div[2]/pre/text()')  # 说说内容
                qq_time = div.xpath('./div[4]/div[1]/span/a/text()')  # 发表时间
                qq_name = qq_name[0] if len(qq_name) > 0 else ''
                qq_content = qq_content[0] if len(qq_content) > 0 else ''
                qq_time = qq_time[0] if len(qq_time) > 0 else ''
                print(qq_name, qq_content, qq_time)
                f.write(qq_content+"\n")
    
        # 当已经到了尾页,“下一页”这个按钮就没有id了,可以结束了
        if driver.page_source.find('pager_next_'+str(next_num)) == -1:
            break
    
        # 找到“下一页”的按钮,因为下一页的按钮是动态变化的,这里需要动态记录一下
        driver.find_element_by_id('pager_next_'+str(next_num)).click()
    
        # “下一页”的id
        next_num += 1
    
        # 因为在下一个循环里首先还有把页面下拉,所以要跳到外层的frame上
        driver.switch_to.parent_frame()  # 切回到主文档
        driver.quit()  # 关闭浏览器
    

    这里一定要设置编码格式,防止后面写入文件时报错

    """
    python2的解决办法
    python 默认编码方式是'ascii',这里我们要设置成'utf-8',否则在处理
    异常的时候会报错,所以我们会设置python默认编码命令(sys.getdefaultencoding())
    可能会报错AttributeError: 'module' object has no attribute 'setdefaultencoding'的错误,这时候我们可以reload(sys),再次执行
    sys.getdefaultencoding()顺利通过,重新执行程序的时候会再次加载sys模块,解决的方法就是reload(sys)
    """
    我用的Python3.6,解决办法是

    encoding ='utf-8'
    

    因为python3.6中reload(sys) 和 sys.getdefaultencoding()不用了

    2、生成词云

    生成词云需要的库
    1、world cloud 生成词云
    2、matplotlib 生成词云图片
    3、

    from wordcloud import WordCloud
    import matplotlib.pyplot as plt
    import jieba
    
    # 生成词云
    def create_word_cloud(filename):
        text = open("{}.txt".format(filename), encoding='utf-8').read()
        # 结巴分词
        wordlist = jieba.cut(text, cut_all=True)
        wl = "".join(wordlist)
    
        # 设置词云
        wc = WordCloud(
            # 设置背景颜色
            background_color="white",
             # 设置最大显示的词云数
           max_words=2000,
             # 这种字体都在电脑字体中,一般路径
           font_path='C:\Windows\Fonts\simfang.ttf',
           height= 1200,
           width= 1600,
            # 设置字体最大值
           max_font_size=100,
            # 设置字体最小值
           min_font_size=8,
         # 设置有多少种随机生成状态,即有多少种配色方案
           random_state=60,
        )
    
        myword = wc.generate(wl)  # 生成词云
        # 展示词云图
        plt.imshow(myword)
        plt.axis("off")
        plt.show()
        wc.to_file('py_book.png')  # 把词云保存下
    
    if __name__ == '__main__':
       create_word_cloud('qq_word')
    
    湿人

    总结

    这次利用selenium动态爬取,这是还是模仿寒大的代码。改成了PYthon3,遇到的问题就是编码问题。网页结构里<frame>之前没有遇到过,这次是遇到的一个大坑。
    再说说最大的坑,浏览器驱动。我在生成词云的时候word cloud安装不上,去pip安装发现还是VC++14.0的问题,我重新配置环境安装vs2015,最后词云生成,再去爬取别人的说说,发现selenium的send.kyes(‘传参’)无法输入,报错是格式错误,但是之前明明运行正常。谁会想到是驱动问题呢,我从半夜1点搞到了快天亮5点半,各种换不同版本的python,换浏览器。早上9点忍不住去星球提问,同时向群里的球友提问,我当时纠结是不是python版本高或者是浏览器版本高,我拼着一股执拗各种安装,还是没有解决问题,最后在想索性再去换换驱动,去GIt上一看,最新的64位驱动和我昨天下载的不一样大,更换驱动。重启,成功运行。对待问题我还是太钻牛角尖 了。唉!被火狐浏览器驱动兼容好误导了!

    相关文章

      网友评论

        本文标题:Python爬虫:动态爬取QQ说说并生成词云,分析朋友状况

        本文链接:https://www.haomeiwen.com/subject/iddadftx.html