发布时间:2018-06-23 15:42:54编辑:Run阅读(4986)
目标分析:
进入百度贴吧,访问: https://tieba.baidu.com/index.html
搜索权利的游戏
定义需要爬取的数据,爬取每个帖子上面的内容
定位到每个帖子,即取 li标签 里面 'class'=' j_thread_list clearfix' 的所有帖子,这个li里面就包含需要的所有内容
title # 帖子标题
post_author # 帖子创建作者
post_time # 帖子创建时间
re_num # 总回复数
content # 最后回复内容
last_author # 最后回复者
last_time # 最后回复时间
获取下一页的url请求
请求地址: http://tieba.baidu.com/f?kw=%E6%9D%83%E5%88%A9%E7%9A%84%E6%B8%B8%E6%88%8F&ie=utf-8&pn=50
图中,可以很明确的看出,每按一次"下一页",pn将增加50,只需求拼接url地址的时候更改pn的值,就可以得到下一页的请求地址
项目实施:
新建一个get_tieba_info.py文件,代码如下:
#!/usr/bin/env python # coding: utf-8 import urllib.request from bs4 import BeautifulSoup from mylog import MyLog as mylog # 导入Mylog类,起别名为mylog class Item(object): # 定义一个Item类,爬取的字段类 title = None # 帖子标题 post_author = None # 帖子创建作者 post_time = None # 帖子创建时间 re_num = None # 总回复数 content = None # 最后回复内容 last_author = None # 最后回复者 last_time = None # 最后回复时间 class GetTieBaInfo(object): def __init__(self, url): self.url = url # 接收一个初始的url地址 self.log = mylog() # 实例化mylog日志类 self.pagesum = 5 # 控制爬取的页面数(一页50条数据) self.urls = self.geturls(self.pagesum) # 获取所有下一页的urls列表 self.items = self.spider(self.urls) # 处理每一页的数据 self.pipelines(self.items) # 数据下载 '''处理url地址,return urls地址列表''' def geturls(self, pagesum): urls = [] pns = [str(i*50) for i in range(pagesum)] # 得到列表['0','50','100'....]即下一页的数字 # ['0', '50', '100', '150', '200'] ul = self.url.split('=') # 以=号为分隔符,切割url地址,得到下面结果 # ['http://tieba.baidu.com/f?kw', '权利的游戏&ie', 'utf-8&pn', '0'] for pn in pns: ul[-1] = pn # ur[-1] = 0 ,50,100,150 url = '='.join(ul) # 以=为拼接符,拼接下一页的url地址 urls.append(url) # 添加到上面的urls列表中 self.log.info(u'获取URLS成功') # 写入日志文件 return urls # 返回urls地址列表 def spider(self, urls): items = [] for url in urls: # 调用self.getresponsecontent函数,返回整个html的内容 HtmlContent = self.getresponsecontent(url) # 使用bs4解析器进行过滤 soup = BeautifulSoup(HtmlContent, 'lxml') # 找到所有符合规则的li标签,返回一个list tagsli = soup.find_all('li', attrs={'class':' j_thread_list clearfix'}) for tag in tagsli: item = Item() # 实例化Item类 # 获取帖子标题 item.title = tag.find('a', attrs={'class':'j_th_tit '}).get_text().strip() # 获取帖子创建作者 item.post_author = tag.find('span', attrs={'class':'frs-author-name-wrap'}).get_text(). strip() # 获取帖子创建时间 item.post_time = tag.find('span', attrs={'class':'pull-right is_show_create_time'}). get_text().strip() # 总回复数 item.re_num = tag.find('span', attrs={'class':'threadlist_rep_num center_text'}). get_text().strip() # 最后回复内容 item.content = tag.find('div', attrs={'class':'threadlist_abs threadlist_abs_onlyline '}). get_text().strip() # 最后回复者 item.last_author = tag.find('span', attrs={'class': 'tb_icon_author_rely j_replyer'}). get_text().strip() # 最后回复时间 item.last_time = tag.find('span', attrs={'class':'threadlist_reply_date pull_right j_reply_data'}).get_text().strip() items.append(item) # 把所有的item,添加到items列表 self.log.info(u'获取标题为<<{}>>的项成功...'.format(item.title)) return items def pipelines(self, items): # 接收一个items列表 filename = u'百度贴吧_权利游戏.txt' with open(filename, 'w', encoding='utf-8') as fp: for item in items: fp.write('帖子标题:{}\n帖子创建作者:{}\n帖子创建时间:{}\n帖子总回复数:\ {}\n帖子最后回复内容:{}\n帖子最后回复者:{}\n帖子最后回复时间:{}\n\n\n\n'\ .format(item.title,item.post_author,item.post_time,item.re_num,item.content,item.last_author,item.last_time)) self.log.info(u'标题为<<{}>>的项输入到 {} 成功'.format(item.title, filename)) def getresponsecontent(self, url): try: page = urllib.request.urlopen(url) html = page.read().decode('utf-8') except: self.log.error(u'python 返回 URL:{} 数据失败'.format(url)) else: self.log.info(u'python 返回 URL:{} 数据成功'.format(url)) return html if __name__ == '__main__': url = 'http://tieba.baidu.com/f?kw=%E6%9D%83%E5%88%A9%E7%9A%84%E6%B8%B8%E6%88%8F&ie=utf-8&pn=0' st = GetTieBaInfo(url)
新建一个mylog.py日志文件,代码如下:
import logging import getpass import sys # 定义MyLog类 class MyLog(object): def __init__(self): self.user = getpass.getuser() # 获取用户 self.logger = logging.getLogger(self.user) self.logger.setLevel(logging.DEBUG) # 日志文件名 self.logfile = sys.argv[0][0:-3] + '.log' # 动态获取调用文件的名字 self.formatter = logging.Formatter('%(asctime)-12s %(levelname)-8s %(message)-12s\r\n') # 日志显示到屏幕上并输出到日志文件内 self.logHand = logging.FileHandler(self.logfile, encoding='utf-8') self.logHand.setFormatter(self.formatter) self.logHand.setLevel(logging.DEBUG) self.logHandSt = logging.StreamHandler() self.logHandSt.setFormatter(self.formatter) self.logHandSt.setLevel(logging.DEBUG) self.logger.addHandler(self.logHand) self.logger.addHandler(self.logHandSt) # 日志的5个级别对应以下的5个函数 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"I'm debug 中文测试") mylog.info(u"I'm info 中文测试") mylog.warn(u"I'm warn 中文测试") mylog.error(u"I'm error 中文测试") mylog.critical(u"I'm critical 中文测试")
运行get_tieba_info.py:
pycharm截图
get_tieba_info.log日志文件生成截图:
百度贴吧_权利游戏.txt截图:
代码分析:
mylog.py模块,主要是为程序提供log功能
log功能很重要,在大量爬取的时候,没有log帮助定位,很难找到错误点
主程序:
get_tieba_info.py也很简单
Item类定义需要获取的数据
GetTieBaInfo类逻辑处理
geturls方法 获取所有需要爬取的url地址
spider方法 提取每个url地址的详细内容
pipelines方法 处理数据,爬取到的数据储存方式,这里使用的是文本txt,这可以存入mysql,redis,mongo等等
getresponsecontent方法 负责发送请求,拿到影响文件(html)
上一篇: beautiful soup爬虫初识
下一篇: bs4爬虫实战二:获取双色球中奖信息
47604
45983
36909
34467
29079
25713
24565
19714
19245
17756
5564°
6155°
5690°
5737°
6704°
5482°
5484°
5988°
5965°
7295°