Python爬取QQ空间留言板

作者: 超神的菠萝 | 来源:发表于2018-05-30 10:39 被阅读48次

    参考
    代码地址

    大致流程

    • 使用selenium登录QQ空间
    • 获取登录后的token
    • 获取登录后的cookies并通过cookies和空间加密算法得到g_tk字串,后期请求链接需要
    • 构造session后期所有请求可以直接使用session
    • 请求留言板数据,转换为json格式,去掉HTML标签存入txt

    使用selenium登录QQ空间

        # path是chromedriver.exe路径
        driver = webdriver.Chrome(path)
        # URL = 'https://user.qzone.qq.com/'
        driver.get(URL)
        # 切换视图,要不然会找不到元素
        driver.switch_to_frame('login_frame')
        # 模拟点击切换账号密码登录
        driver.find_element_by_id('switcher_plogin').click()
        # 自动输入QQ账号
        driver.find_element_by_id('u').send_keys(user)
        # 自动输入QQ密码
        driver.find_element_by_id('p').send_keys(pwd)
        # 模拟登陆点击
        driver.find_element_by_id('login_button').click()
    

    获取token

        html = driver.page_source
        xpat = r'window\.g_qzonetoken = \(function\(\)\{ try{return \"(.*)";'
        qzonetoken = re.compile(xpat).findall(html)[0]
    

    获取cookies,获取g_tk

        realCookie = {}
        print(cookies)
        for elem in cookies:
            realCookie[elem['name']] = elem['value']
        g_tk = get_g_tk(realCookie)
    
    def get_g_tk(cookie):
        hashes = 5381
        for letter in cookie['p_skey']:
            hashes += (hashes << 5) + ord(letter)  # ord()是用来返回字符的ascii码
        return hashes & 0x7fffffff
    

    获取session

    def back_session(realCookie):
        session = requests.session()
        c = requests.utils.cookiejar_from_dict(realCookie, cookiejar=None, overwrite=True)
        session.headers = headers
        session.cookies.update(c)
        return session
    

    保存留言板,通过递归实现

    #保存留言板
    def saveWords(session, gtk, token, start=0, limit=10):
        print('当前下载第%d页数据'%(start/10+1))
        url = 'https://user.qzone.qq.com/proxy/domain/m.qzone.qq.com' \
              '/cgi-bin/new/get_msgb?uin=%s&hostUin=%s&start=%s' \
              '&s=0.1698142305644994&format=jsonp&%s=10&inCharset=utf-8' \
              '&outCharset=utf-8&g_tk=%s&qzonetoken=%s&g_tk=%s' % (user, user, start, limit, gtk, token, gtk)
        res = session.get(url)
        text = res.text
        #去掉返回json中的_CallBack以及后面的); 才能格式化为json
        text = text[10:-3]
        j = json.loads(text)
        total = j['data']['total']
        
        with open(txt+'txt', 'a', encoding='UTF-8') as f:
            if start == 0:
                f.write('总共有%s条留言\n' % total)
            f.write('当前下载第%d页数据\n'%(start/10+1))
            for value in j['data']['commentList']:
                cont = str(value['pubtime']) + ' ' + str(value['uin']) + '-' + str(value['nickname']) + ':' + str(
                    value['htmlContent']) + '\n'
                f.write(filter_tags(cont))
    
        if start>=total:
            return
        start = start+10
        saveWords(session,gtk,token,start)
    

    去掉没用的标签,网上找的工具类

    ##过滤HTML中的标签
    #将HTML中标签等信息去掉
    #@param htmlstr HTML字符串.
    def filter_tags(htmlstr):
        #先过滤CDATA
        re_cdata=re.compile('//<!\[CDATA\[[^>]*//\]\]>',re.I) #匹配CDATA
        re_script=re.compile('<\s*script[^>]*>[^<]*<\s*/\s*script\s*>',re.I)#Script
        re_style=re.compile('<\s*style[^>]*>[^<]*<\s*/\s*style\s*>',re.I)#style
        re_br=re.compile('<br\s*?/?>')#处理换行
        re_h=re.compile('</?\w+[^>]*>')#HTML标签
        re_comment=re.compile('<!--[^>]*-->')#HTML注释
        s=re_cdata.sub('',htmlstr)#去掉CDATA
        s=re_script.sub('',s) #去掉SCRIPT
        s=re_style.sub('',s)#去掉style
        s=re_br.sub('\n',s)#将br转换为换行
        s=re_h.sub('',s) #去掉HTML 标签
        s=re_comment.sub('',s)#去掉HTML注释
        #去掉多余的空行
        blank_line=re.compile('\n+')
        s=blank_line.sub('\n',s)
        s=replaceCharEntity(s)#替换实体
        return s
    
    ##替换常用HTML字符实体.
    #使用正常的字符替换HTML中特殊的字符实体.
    #你可以添加新的实体字符到CHAR_ENTITIES中,处理更多HTML字符实体.
    #@param htmlstr HTML字符串.
    def replaceCharEntity(htmlstr):
        CHAR_ENTITIES={'nbsp':' ','160':' ',
                    'lt':'<','60':'<',
                    'gt':'>','62':'>',
                    'amp':'&','38':'&',
                    'quot':'"','34':'"',}
    
        re_charEntity=re.compile(r'&#?(?P<name>\w+);')
        sz=re_charEntity.search(htmlstr)
        while sz:
            entity=sz.group()#entity全称,如&gt;
            key=sz.group('name')#去除&;后entity,如&gt;为gt
            try:
                htmlstr=re_charEntity.sub(CHAR_ENTITIES[key],htmlstr,1)
                sz=re_charEntity.search(htmlstr)
            except KeyError:
                #以空串代替
                htmlstr=re_charEntity.sub('',htmlstr,1)
                sz=re_charEntity.search(htmlstr)
        return htmlstr
    
    def repalce(s,re_exp,repl_string):
        return re_exp.sub(repl_string,s)
    

    效果

    image.png

    最后再贴一下代码地址

    代码地址

    相关文章

      网友评论

        本文标题:Python爬取QQ空间留言板

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