百度贴吧爬虫

利用requests、正则表达式和Beautiful爬取贴吧用户名、评论和图片

    定义工具类——去除爬取项多余内容

class Tool():
    removeImg = re.compile('<img.*?>|{7}|&nbsp;') # 去除img标签,1-7位空格,&nbsp;
    removeAddr = re.compile('<a.*?>|</a>') # 删除超链接标签
    replaceLine = re.compile('<tr>|<div>|</div>|</p>') # 把换行的标签换位\n
    replaceTD = re.compile('<td>') # 把表格制表<td>换为\t
    replaceBR = re.compile('<br><br>|<br>|</br>|</br></br>') # 把换行符或者双换行符换为\n
    removeExtraTag = re.compile('.*?') # 把其余标签剔除
    removeNoneLine = re.compile('\n+') # 把多余空行删除
    
    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.replaceBR, "\n", x)
        x = re.sub(self.removeExtraTag, "", x)
        x = re.sub(self.removeNoneLine, "\n", x)
        return x.strip() # 把strip()前后多余内容删除

    帖子标题、页数都可以在第一个链接页面找到相关数据,图片等也是直接用正则表达式进行获取

class Spider():
    def __init__(self):
        self.tool = Tool()

    # 获取源码
    def getSource(self, url):
        user_agents = ['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0',
                       'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0',
                       'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533+ \(KHTML, like Gecko) Element Browser 5.0',
                       'IBM WebExplorer /v0.94', 'Galaxy/1.0 [en] (Mac OS X 10.5.6; U; en)',
                       'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',
                       'Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14',
                       'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) \Version/6.0 Mobile/10A5355d Safari/8536.25',
                       'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) \Chrome/28.0.1468.0 Safari/537.36',
                       'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; TheWorld)']
        # user_agent在一堆范围中随机获取
        # random.randint()获取随机数,防止网站认出是爬虫而访问受限
        index = random.randint(0, 9)
        user_agent = user_agents[index]
        headers = {'User_agent': user_agent}
        html = requests.get(url, headers=headers)
        return html.text

    # 获取帖子标题
    def getTitle(self, url):
        result = self.getSource(url)
        pattern = re.compile('<h1.*?title.*?>(.*?)</h1>', re.S)
        items = re.search(pattern, result)
        print('这篇帖子标题为:', self.tool.replace(items.group(1)))

    # 获取帖子总页数
    def getPageNumber(self, url):
        result = self.getSource(url)
        pattern = re.compile('<ul.*?l_posts_num.*?<span class="red">(.*?)</span>', re.S)
        items = re.search(pattern, result).group(1)
        print('帖子共有', items, '页')
        return items

    def getContent(self, url):
        result = self.getSource(url)
        pattern = re.compile('<a data-field.*?p_author_name.*?">(.*?)</a>.*?<div id="post_content_.*?>(.*?)</div>',
                                 re.S)
        items = re.findall(pattern, result)
        # 获取楼层数可以直接用循环,省去正则匹配的麻烦
        number = 1
        for item in items:
            # item[0]为楼主,item[1]为发言内容,使用\n换行符打出内容更干净利落
            # item[1]中可能有img链接,用自定义Tool工具清洗
            print('\n', number, '楼', '\n楼主:', item[0], '\n内容:', self.tool.replace(item[1]))
            time.sleep(0.01)
            number += 1

        # 获取晒图,清洗获得链接并保存入list
    def getImage(self, url):
        result = self.getSource(url)
        soup = BeautifulSoup(result, 'lxml')
        # 此处用BeautifulSoup显然更高效
        # find_all()返回一个list,find()返回一个元素
        # 注意class属性和python内置的重合,所以加_变成class_
        items = soup.find_all('img', class_="BDE_Image")
        images = []
        number = 0
        for item in items:
            print('发现一张图,链接为:', item['src'])
            images.append(item['src'])
            number += 1
        if number >= 1:
            print('\n', '共晒图', number, '张,厉害了我的哥!!!')
        else:
            print('喏,没有图......')
        return images

    创建目录进行图片保存

# 创建目录
    def makeDir(self, path):
        self.path = path.strip()
        # E = os.path.exists(os.path.join(os.getcwd(), self.path))
        E = os.path.exists(self.path)
        if not E:
            # 创建新目录,若想将内容保存至别的路径(非系统默认),需要更环境变量
            # 更改环境变量用os.chdir()
            # os.makedirs(os.path.join(os.getcwd(), self.path))
            os.mkdir(self.path)
            # os.chdir(os.path.join(os.getcwd(), self.path))
            print('正在创建名为', self.path, '的文件夹')
            return self.path
        else:
            print('名为', self.path, '的文件夹已经存在...')
            return False

    def saveImage(self, detailURL, name):
        try:
            data = requests.get(detailURL, timeout=10).content
            # 保存文件,一定要用绝对路径      `
            # 所以设置self.path,是为了方便后面函数无障碍调用
        except requests.exceptions.ConnectionError:
            print('下载图片失败')
            return None
        fileName = name + '.' + 'jpg'
        fileName = os.path.join(self.path, name+'.jpg')
        f = open(fileName, 'wb')
        f.write(data)
        f.close()
        print('成功保存图片', fileName)

    获取所有页面——主要代码逻辑

    def getAllPage(self):
        self.siteURL = 'http://tieba.baidu.com/p/5862596971'
        # 获取帖子标题
        self.getTitle(self.siteURL)
        # 获取帖子页数
        numbers = self.getPageNumber(self.siteURL)
        for page in range(1, int(numbers) + 1):
            # 格式化索引链接
            self.url = self.siteURL + '?pn=' + str(page)
            print('\n\n', '正准备获取第', page, '页的内容...')
            # 获取评论
            print('\n', '正准备获取评论...')
            self.getContent(self.url)
            # 每一页创建一个文件
            self.makeDir(path='page' + str(page))
            # 获取图片
            print('\n', '正准备获取图片...')
            images = self.getImage(self.url)
            print('\n', '正准备保存图片...')
            number = 1
            # 保存图片,先从之前的list中找链接
            for detailURL in images:
                name = 'page' + str(page) + '_'+'num' + str(number)
                self.saveImage(detailURL, name)
                time.sleep(0.1)
                number += 1

            print('\n\n', '完成第', page, u'页')
        print('\n\n', '恭喜,圆满成功!')
  • 代码过程中对于用户名中含有特殊符号(图片)的会直接返回链接,改良中
  • 更多爬虫代码详情参考Githun
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 声明:本文讲解的实战内容,均仅用于学习交流,请勿用于任何商业用途! 一、前言 强烈建议:请在电脑的陪同下,阅读本文...
    Bruce_Szh阅读 12,674评论 6 28
  • 1. 概述 本文主要介绍网络爬虫,采用的实现语言为Python,目的在于阐述网络爬虫的原理和实现,并且对目前常见的...
    Lemon_Home阅读 2,723评论 0 21
  • HTTP基本原理 URI、URL、URN(Uninform Resource) URI(Identifier):统...
    GHope阅读 2,059评论 2 26
  • 我们其实都说过一句话“我很了解你”但是反问了自己“你真的了解在你面前这个人么?” 没人知道除了自己以外其他人的想法...
    享受一人宁静阅读 434评论 0 0
  • 今天一大早起来刷朋友圈,王宝强在微博发表的离婚声明赫然吸引住我的眼球,直觉告诉我,这是爆炸性的新闻。果不其然,随后...
    夏天的田格子阅读 913评论 0 3