当前位置 博文首页 > ChenYX的博客:【Python学习1:爬取百度贴吧并按回复量生成排序

    ChenYX的博客:【Python学习1:爬取百度贴吧并按回复量生成排序

    作者:[db:作者] 时间:2021-07-22 09:28

    这段时间宅在家里,被疫情弄得都要发霉了。

    为了打发无聊时光,跟着CSDN上的速成班学了一下Python以及爬虫。突然发现这玩意也太厉害了,以前只以为是个获得数据的工具,现在才发现,这玩意最强悍的是应用在数据筛选和清理。真不愧是现在最火的语言,论代码的简介性和面向对象的友好性上绝不是之前学的那一票面向过程的语言可以比的。要是早知道这玩意,该能省下多少事,唉……我的大好青春……

    不说废话,学完了这几天的课程,我跃跃欲试,决定活学活用一把,做一个可以爬贴吧的爬虫:

    import urllib.parse as up
    import urllib.request as ur
    import lxml.etree as le
    import operator
    
    kw = str(input('请输入词条: '))
    start_page = int(input('请输入起始页面: '))
    final_page = int(input('请输入结束页面: '))
    
    fin_data = []
    Num = 0

    首先调模块,urllib的库以及lxml的库都是必须滴~(话说这lxml的库单装真不是我等凡人可以搞定的,为了装这个龟孙子我又上外网又是找镜像,最后还是装不上去。等看完凌晨四点的我知道还有Anaconda这个东西之后只剩下了:*~@*%)

    除了调模块还有输入声明,词条和页码单独拿出来给输入,这样想搜啥都行。

    for i in range(start_page, final_page+1):
        pn = i
        user_data = {
            'kw': kw,
            'ie': 'utf-8',
            # 'cid': None,
            # 'tab': 'corearea',
            'pn': str(pn*50-50)
        }
        data_url = up.urlencode(
            user_data
        )
        print('正在检索第%d页……' % pn)
        request = ur.Request('https://tieba.baidu.com/f?'+data_url)      # 将url格式粘合后请求页面
        response = ur.urlopen(request).read()                           # 将页面导入
    
        # with open('%s.html' % kw,'wb') as f:
        #      f.write(response)
        html_x = le.HTML(response)                                  # 将url地址转换成xpath文件
        root_path = '//div[@class="t_con cleafix"]'
        rep_num_path = './div[@class="col2_left j_threadlist_li_left"]/span/text()'        # 回复数地址
        title_path = './div[@class="col2_right j_threadlist_li_right "]/div/div/a/text()'  # 标题地址
        link_path = './div[@class="col2_right j_threadlist_li_right "]/div/div/a/@href'    # 链接地址
        # author_path = './div/div/div/span[contains(@title,"主题作者")]/@title'            # 作者地址
        creatTime_path = './div/div/div/span[contains(@title,"创建时间")]/text()'           # 创建时间地址
        # replier_path = './div/div/div/span[contains(@title,"最后回复人")]/@title'         # 最后回复者地址
        replyTime_path = './div/div/div/span[contains(@title,"最后回复时间")]/text()'        # 最后回复时间地址
        # pic_path = root_path + './div/div/div/div/div/div/ul/li/a/img/@bpic'                # 图片地址
        # video_path = root_path + './div/div/div/div/div/div/ul/li/div/a/@get_data-video'        # 视频地址
    
        div_x_s = html_x.xpath(root_path)
        for i,div_x in enumerate(div_x_s):
             rep_num = (int(div_x.xpath(rep_num_path)[0]))
             rep_num_s = str(rep_num)
             title_s = str(div_x.xpath(title_path)[0])
             link_s = 'https://tieba.baidu.com' + str(div_x.xpath(link_path)[0])
             rep_time_s = ''
             if div_x.xpath(replyTime_path):
                 rep_time_s = str(div_x.xpath(replyTime_path)[0]).replace('\r\n', '').rstrip().lstrip()
             else:
                 rep_time_s = 'Notime'
             cre_time_s = str(div_x.xpath(creatTime_path)[0])
             # pic_s = div_x.xpath(pic_path)[0]
             # video__s = div_x.xpath(video_path)[0]
    
             temp_data = {
                 '编号': Num + i,
                 '标题': title_s,
                 '链接': link_s,
                 '回复时间': rep_time_s,
                 '创建时间': cre_time_s,
                 '回帖数量': rep_num
             }
             fin_data.append(temp_data)
             # print(temp_data)
        Num += len(div_x_s)

    这是巨长的主要代码段(第一次写,如果有大佬看了不要喷我)

    外层for用来重复访问选定的页面;

    user_data用来保存对应的用户请求字段,这里面包括“kw”、“ie”、“pn”三段
    kw:表示访问词条;ie:表示访问的编码方式;pn:表示访问的页码,百度规则下和实际页码对应了个50倍的关系

    将用户段定义好之后就开始和初始url粘合,并调用urllib两个库将页面拿下来并导入内存。

    然后就是url地址转换成xpath地址列表,对列表进行检索。root_path是贴吧每一栏有用信息包含的标签,剩下的都是在这个标签下各个有用字段标签的xpath地址,我把觉得有用的xpath地址都保留了下来,回头也可以用这些爬图片视频什么的。

    在第二个for循环里对几个有用的xpath对象进行提取并转换成字符串在后面写入fin_data列表保存。其中回帖数量也就是rep_num取回来进行后面排序挑出热门的帖子。

    这里面有个有意思的就是最后一次回帖时间,经过比较发现并不是每个帖子都有这一项,所以要做一次判断,如果没时间就给个“NoTime”。(看了一下基本上就是首页的几个置顶帖什么的)

    最后还给每个帖子编了个号,用num记一下现在的检索总量。

    fin_data.sort(key = operator.itemgetter('回帖数量'), reverse= True)
    print('输出完成,回复量最多的5条帖子及链接如下:')
    data_s = ''
    for i ,value in enumerate(fin_data):
        data_s += str(value) + '\n'
        if  i == 4:
            print(data_s)
    data_s = data_s.encode(encoding='utf-8')
    with open('%s贴吧热点.txt' % kw, 'wb') as f:
        f.write(data_s)
    print('详细信息请访问根目录,按任意键退出。')
    while input():
        break

    最后离开循环之后,就是排序了。这个地方排序的关键词选择用的是operator.itemgetter()这个方法里调用的函数,它返回的是一个函数,然后这个函数给了key再由sort方法来调。(反正这东西有点玄妙,具体还得研究一下。)

    最后就是字符串的生成,为了好看用个循环把他分段,再用文件流写到txt文件里,并打印出前五个热点文章及地址。

    最后的最后,尝试将这个py文件导出exe文件,这要用到三方包:PyInstaller,具体流程参考这个老哥的文章:https://blog.csdn.net/zwx19921215/article/details/85234801

    运行导出exe之后下面terminal里显示的信息,最后显示successfully
    cs