Python爬取百度贴吧内容

Posted 思念殇千寻

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python爬取百度贴吧内容相关的知识,希望对你有一定的参考价值。

  参考资料:https://cuiqingcai.com/993.html 

  即 静觅 » Python爬虫实战二之爬取百度贴吧帖子

  我最近在忙学校的一个小项目的时候涉及到NLP的内容。但是在考虑如何训练的时候却才懂什么叫巧妇难为无米之炊的滋味。中文语料库实在少的可怜,偶尔有一两个带标签的语料库,拿出一看,标注惨不忍睹,都让我怀疑是不是机器标注的。正应了那句话,人工智能,有多少智能就有多少人工。

  有什么办法呢,硬着头皮,走一步是一步吧,总比停滞不前要好。项目涉及到帖子,那么我相信不管是谁,首先想到的就是最大的中文贴吧:百度贴吧。我的目标就是爬取百度贴吧的帖子中的内容。

  其实参考资料的那篇文章已经将步骤写得十分详细了,但是因为那篇文章的最后更新时间也只是在2016年,如今百度贴吧已有所改版,代码可能不太好用(如原作者所说,问题大多出现在正则表达式上),于是自己学习摸索着将代码跑起来,下面记录在此。

  1.导入和Spider有关的包

import urllib.error
import urllib.request
import re

  首先urllib是python的一个标准库,在此的作用就是向服务器发送一个请求(request),然后收到返回的一个response。一个奇怪的事情是假如在notebook中跑代码,只需要import urllib就行了。但是在直接运行脚本的时候却要import urllib.error和request,不然会报错说没有这个包。

  re则是一个关于正则表达式的标准库,用途非常广泛,用好了事半功倍,必须好好掌握。

  

  2.构造一个包含对网页各种操作的类BDTB

class BDTB:
    def __init__(self, baseUrl, seeLZ):
        self.baseURL = baseURL
        self.seeLZ = \'?see_lz=\'+str(seeLZ)
        self.tool = Tool()

    def getPage(self, pageNum):
        try:
            url = self.baseURL + self.seeLZ + \'&pn=\' + str(pageNum)
            response = urllib.request.urlopen(url)
            # print(response.read())
            return response
        except urllib.error.URLError as e:
            if hasattr(e,  "reason"):
                print(\'连接百度贴吧失败,错误原因\' + e.reason)
                return None

    def getTitle(self):
        page = self.getPage(1)
        pattern = re.compile(\'<title>(.*?)</title>\', re.S)
        result = re.search(pattern, page.read().decode(\'utf-8\'))
        if result:
            # print result.group(1)  #测试输出
            return result.group(1).strip()
        else:
            return None

    def getPageNum(self):
        page = self.getPage(1)
        pattern = re.compile(\'<li class="l_reply_num".*?</span>.*?<span.*?>(.*?)</span>\', re.S)
        result = re.search(pattern, page.read().decode(\'utf-8\'))
        if result:
            # print result.group(1)  #测试输出
            return result.group(1).strip()
        else:
            return None

    def getContent(self, page):
        pattern = re.compile(\'<div id="post_content_.*?>(.*?)</div> | <div class="post_bubble_middle">(.*?)</div>\', re.S)
        items = re.findall(pattern, page.read().decode(\'utf-8\'))
        for item in items:
            if(len(self.tool.replace(item[0])) > 0):
                print(self.tool.replace(item[0]))
        return items

  这个类包含了4个类方法和一个构造方法,四个方法分别能获取帖子的HTML,页数,标题和内容,关于这四个方法的设计参考资料中讲的非常透彻,就不再详述了。

 

  3.再定义一个Tool类对爬取的网页内容进行后续处理(定义在BDTB前)

class Tool:
    # 去除img标签,7位长空格
    removeImg = re.compile(\'<img.*?>| {7}|\')
    # 删除超链接标签
    removeAddr = re.compile(\'<a.*?>|</a>\')
    # 把换行的标签换为\\n
    replaceLine = re.compile(\'<tr>|<div>|</div>|</p>\')
    # 将表格制表<td>替换为\\t
    replaceTD = re.compile(\'<td>\')
    # 把段落开头换为\\n加空两格
    replacePara = re.compile(\'<p.*?>\')
    # 将换行符或双换行符替换为\\n
    replaceBR = re.compile(\'<br><br>|<br>\')
    # 将其余标签剔除
    removeExtraTag = re.compile(\'<.*?>\')

    def replace(self, x):
        x = re.sub(self.removeImg, "", x)
        x = re.sub(self.removeAddr, "", x)
        x = re.sub(self.replaceLine, "\\n", x)
        x = re.sub(self.replaceTD, "\\t", x)
        x = re.sub(self.replacePara, "\\n    ", x)
        x = re.sub(self.replaceBR, "\\n", x)
        x = re.sub(self.removeExtraTag, "", x)
        # strip()将前后多余内容删除
        return x.strip()

  这个类的作用就是将Spider爬取的正文规范化,去除掉了很多多余的东西,图片链接啊之类的。前后对比效果参考资料里也是有的。

 

  4.大功告成,调用看看

baseURL = \'https://tieba.baidu.com/p/6462468634\'
bdtb = BDTB(baseURL, 0)
page = bdtb.getPage(1)
items = bdtb.getContent(page)  

  输出效果如下:

   对比原帖子,一楼是楼主的长文,之后是网友的跟帖。我没有为了美观加入分割线,读者想加的话非常简单,最后的阅读效果应该是非常好的。

   经过以上几个步骤就可以获得能够进行NLP处理的一段一段的贴文了,也可以进行人工标注了(还是无从下手啊),是不是很简单~~

  题外话:参考资料的文章最后更新于2016年,那年科比退役。昨日这位巨星不幸逝世...2020年迎来一个地狱般的开局。即便这样还是要努力去生活,一切都会好起来的!

以上是关于Python爬取百度贴吧内容的主要内容,如果未能解决你的问题,请参考以下文章

Python爬虫实战二之爬取百度贴吧帖子

Python爬取百度贴吧内容

Python爬虫实战之如何爬取百度贴吧帖子?案例详解

Python爬虫实战之如何爬取百度贴吧帖子?案例详解

python爬虫—爬取百度百科数据

转 Python爬虫实战二之爬取百度贴吧帖子