BeautifulSoup简单爬取百度贴吧

BeautifulSoup简单爬取百度贴吧()

一.分析百度贴吧网页信息
注意:本人使用的环境为python3.6+pycharm2017.2.4

我们以百度贴吧权利的游戏吧为例:http://tieba.baidu.com/f?ie=utf-8&kw=权利的游戏&fr=search
分析网页我们发现规律:

这里写图片描述

这里写图片描述

每换一页pn增加50 这个在我们抓取每页信息循环页数的时候用得上。
好了我们现在来分析下我们需要获取的东西有哪些?

1.话题

2.作者id

3.最后回复者的id

4.最后回复时间

这里写图片描述

二.编写代码

1.日志部分

为了方便我们查看我们的操作记录我们写一个MyLog类打印日志信息

#! -*- encoding:utf-8 -*-\
"""
乱码问题 解决方式一:#! -*- encoding:utf-8 -*-
          方式二:u'哈哈哈'  字符串以unicode格式存储
"""
import logging
import getpass
import sys

class MyLog(object):
    #构造方法
    def __init__(self):
        self.user=getpass.getuser()
        self.logger=logging.getLogger(self.user)
        self.logger.setLevel(   logging.DEBUG )  
        #日志的级别  critical error warn info  debug

        #定义日志文件
# 从命令行参数中取出第一个参数,并取从0开始到   倒数第三个字符    拼接成文件名
        self.formatter=logging.Formatter('%(asctime) -12s %(levelname) -8s %(name) -10s %(message)-12s\r\n')  #日志输出的格式

        #日志输出到文件    logging有三个内置的Handler,
        self.logHand=logging.FileHandler(self.logFile, encoding='utf8')
        self.logHand.setFormatter(   self.formatter  )   #设置 格式
        self.logHand.setLevel(   logging.DEBUG )  #设置 级别

        #日志输出 到屏幕,这是标准输出流
        self.logHandSt=logging.StreamHandler()
        self.logHandSt.setFormatter(  self.formatter )
        self.logHand.setLevel(  logging.DEBUG )

        #将两个Handler加入到  logger中
        self.logger.addHandler(   self.logHand )
        self.logger.addHandler(    self.logHandSt )

    #重新定义logger中的日志输出的级别的方法
    def debug(self,msg):
        self.logger.debug(msg)

    def  info(self,msg):
        self.logger.info(msg)

    def warn(self,msg):
        self.logger.warn(msg)

    def error(self,msg):
        self.logger.error(msg)

    def critical(self,msg):
        self.logger.critical(msg)

if __name__=='__main__':
    mylog=MyLog()
    mylog.debug(u'debug测试')
    mylog.info(u'info测试')
    mylog.warn(u'warn测试')
    mylog.error(u'error测试')
    mylog.critical(u'critical测试')

2.获取url
一般爬虫爬取信息可分为三部分:1.获取url 2.爬取信息 3.信息保存
1)获取url
根据我们上面图片的分析开始编写代码:

self.pageSum=1#要爬取的页数
#单独定义一个保存目标网站url的类
# 根据pageSum拼装要爬取的地址   思考一 :如何确定总共有多少页数?
    def getUrls(self,pageSum):
        urls=[]
        pns=[ str(i*50) for i in range(pageSum)]
        ul=self.url.split('=')
        for pn in pns:
            ul[-1]=pn   #取最后一个'=' 也就是页数对应的数值  替换页数 0 50 100 150 200
            url='='.join( ul )
            urls.append( url )
            self.log.debug('----待爬取的地址有:'+url)
        self.log.info(u'获取URL成功')
        return urls

2)爬虫部分
数据爬取我们利用lxml解析的方式。同样我们定义一个类spider。

    def spider(self,urls):
        items=[]
        for url in urls:
            htmlContent=self.getResponseContent(url)
            soup=BeautifulSoup(htmlContent,'lxml')
            tagsli=soup.find_all('li',attrs={'class':' j_thread_list clearfix'})
            for tag in tagsli:
                item=Item()
                item.title=tag.find('a',attrs={'class':'j_th_tit '}).get_text().strip()
                item.author=tag.find('div',attrs={'class':'threadlist_author pull_right'}).span['title']
                #item.author = tag.find('span', attrs={'class': 'tb_icon_author '}).get('title') 错误
                item.lastreplypeople= tag.find('span', attrs={'class': 'tb_icon_author_rely j_replyer'})['title']
                item.lastreplytime=tag.find('span', attrs={'class': 'threadlist_reply_date pull_right j_reply_data'}).getText().strip()

                items.append(item)
                #self.log.info(u'获取标题为 -->%s--< 的帖子成功 作者是:%s' %(item.title,item.author))
                self.log.info(u'获取标题为 -->%s--< 的帖子成功' % (item.title))
        return items

3)数据保存

 # 保存爬取的文件
    def pipelines(self,items):
        fileName=u'百度贴吧.txt'.encode('utf8')
        with codecs.open(fileName,'w','utf8') as fp:
            for item in items:
                fp.write('%s %s %s %s\t\t  \r\n' %(item.title,item.author,item.lastreplypeople,item.lastreplytime))
                #fp.write('%s \r\n' % (item.title))
                self.log.info(u'标题为 -->%s<-- 的帖子保存成功' %(item.title))

4)打开网页当然还需要另外一个类来获取网页数据

 def getResponseContent(self,url):
        #对地址的中文进行编码
        try:
            url=quote(url,safe=string.printable)
            response=urllib.request.urlopen(url)
        except  error.URLError as e:
            self.log.error(u'python爬取%s 出错了' %url)
            print (e)
        else:
            self.log.info(u'python爬取%s 成功' %url)
            return response.read()

三.总结
爬取信息部分值得注意的是 分析网页定位元素的时候一定细心。多尝试。如何产看网页源代码应该不用说明了吧 哈哈
最后附上源码:

#! -*- encoding:utf-8 -*-\

from MyLog import MyLog
import string
from urllib.parse import quote
from urllib import error
import urllib.request
from bs4 import BeautifulSoup
import  codecs


class Item(object):
    title=None
    author=None
    lastreplypeople = None
    lastreplytime=None

class GetBaiTieBa(object):
    def __init__(self,url):
        self.url=url
        self.log=MyLog()
        self.pageSum=1#要爬取的页数
        self.urls=self.getUrls(self.pageSum) #根据pageSum拼装要爬取的地址
       #开始爬取
        self.items=self.spider(self.urls)
        #存
        self.pipelines(self.items)


    # 根据pageSum拼装要爬取的地址   思考一 :如何确定总共有多少页数?
    def getUrls(self,pageSum):
        urls=[]
        pns=[ str(i*50) for i in range(pageSum)]
        ul=self.url.split('=')
        for pn in pns:
            ul[-1]=pn   #取最后一个'=' 也就是页数对应的数值  替换页数 0 50 100 150 200
            url='='.join( ul )
            urls.append( url )
            self.log.debug('----待爬取的地址有:'+url)
        self.log.info(u'获取URL成功')
        return urls

    #数据爬取 利用lxml解析
    def spider(self,urls):
        items=[]
        for url in urls:
            htmlContent=self.getResponseContent(url)
            soup=BeautifulSoup(htmlContent,'lxml')
            tagsli=soup.find_all('li',attrs={'class':' j_thread_list clearfix'})
            for tag in tagsli:
                item=Item()
                item.title=tag.find('a',attrs={'class':'j_th_tit '}).get_text().strip()
                item.author=tag.find('div',attrs={'class':'threadlist_author pull_right'}).span['title']
                #item.author = tag.find('span', attrs={'class': 'tb_icon_author '}).get('title') 错误
                item.lastreplypeople= tag.find('span', attrs={'class': 'tb_icon_author_rely j_replyer'})['title']
                item.lastreplytime=tag.find('span', attrs={'class': 'threadlist_reply_date pull_right j_reply_data'}).getText().strip()

                items.append(item)
                #self.log.info(u'获取标题为 -->%s--< 的帖子成功 作者是:%s' %(item.title,item.author))
                self.log.info(u'获取标题为 -->%s--< 的帖子成功' % (item.title))
        return items

    def getResponseContent(self,url):
        #对地址的中文进行编码
        try:
            url=quote(url,safe=string.printable)
            response=urllib.request.urlopen(url)
        except  error.URLError as e:
            self.log.error(u'python爬取%s 出错了' %url)
            print (e)
        else:
            self.log.info(u'python爬取%s 成功' %url)
            return response.read()

    # 保存爬取的文件
    def pipelines(self,items):
        fileName=u'百度贴吧.txt'.encode('utf8')
        with codecs.open(fileName,'w','utf8') as fp:
            for item in items:
                fp.write('%s %s %s %s\t\t  \r\n' %(item.title,item.author,item.lastreplypeople,item.lastreplytime))
                #fp.write('%s \r\n' % (item.title))
                self.log.info(u'标题为 -->%s<-- 的帖子保存成功' %(item.title))

if __name__=='__main__':
    url=u'http://tieba.baidu.com/f?kw=权利的游戏&ie=utf-8&pn=50'
    print ('url:',url)
    tb=GetBaiTieBa(url)

保存的text:
这里写图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值