Python爬取QQ空间留言板

参考
代码地址

大致流程

  • 使用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('//]*//\]\]>',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('')#处理换行
    re_h=re.compile(']*>')#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\w+);')
    sz=re_charEntity.search(htmlstr)
    while sz:
        entity=sz.group()#entity全称,如>
        key=sz.group('name')#去除&;后entity,如>为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)

效果

Python爬取QQ空间留言板_第1张图片
image.png

最后再贴一下代码地址

代码地址

你可能感兴趣的:(Python爬取QQ空间留言板)