一次性付费进群,长期免费索取教程,没有付费教程。
教程列表见微信公众号底部菜单 |本文底部有推荐书籍
微信公众号:计算机与网络安全
ID:Computer-network
经常在网上追剧,偶尔也在百度贴吧上看看美剧贴,可又比较懒,天天登录贴吧查看贴子觉得很麻烦。干脆就写个爬虫让它自动爬内容好了,有空就看看哪些帖子回复了,又有哪些新贴。这里以百度贴吧里的“权利的游戏吧”为例。
1、目标分析
图1 编码转换
在浏览器(这里使用的是Chrome浏览器,其他浏览器基本上都差不多)中打开这个URL,查看帖子标题,如图2所示。
图2 bs4爬虫来源页面
图3 所需数据位置
找到所需数据的位置后,仔细观察一下,发现所有帖子都有一个共同的标签
(这个标签还有其他的属性,只需要一个共同的属性就够了)。所以只需要用bs4过滤器find_all找到所有的标签,然后再进一步分离出所需的数据就可以了。
2、项目实施
既然思路都已经明确了,那就开工吧。打开Eclipse,单击New图标右侧的三角按钮,在弹出菜单中选择PyDev Project项,如图4所示。
图4 Eclipse创建Python新项目
在弹出的对话框中输入项目名称,单击Finish按钮,如图5所示。
图5 输入项目名
图6 在项目中创建Python文件
图7 Python文件名
1 #!/usr/bin/evn python3
2 #-*- coding: utf-8 -*-
3 '''
4 Created on 2016年8月9日
5
7 '''
8
9
10 import urllib.request
11 import urllib.parse
12 from bs4 import BeautifulSoup
13 from mylog import MyLog as mylog
14 import codecs
15
16
17 class Item(object):
18 title = None #帖子标题
19 firstAuthor = None #帖子创建者
20 firstTime = None #帖子创建时间
21 reNum = None #总回复数
22 content = None #最后回复内容
23 lastAuthor = None #最后回复者
24 lastTime = None #最后回复时间
25
26
27 class GetTiebaInfo(object):
28 def __init__(self,url):
29 self.url = url
30 self.log = mylog()
31 self.pageSum = 5
32 self.urls = self.getUrls(self.pageSum)
33 self.items = self.spider(self.urls)
34 self.pipelines(self.items)
35
36 def getUrls(self,pageSum):
37 urls = []
38 pns = [str(i*50) for i in range(pageSum)]
40 for pn in pns:
41 ul[-1] = pn
42 url = '='.join(ul)
43 urls.append(url)
45 return urls
46
47 def spider(self, urls):
48 items = []
49 for url in urls:
50 htmlContent = self.getResponseContent(url)
51 soup = BeautifulSoup(htmlContent, 'lxml')
52 tagsli = soup.find_all('li',attrs={'class':' j_thread_listclearfix'})
53 for tag in tagsli:
54 item = Item()
55 item.title = tag.find('a',attrs={'class':'j_th_tit'}).get_text().strip()
56 item.firstAuthor = tag.find('span', attrs={'class':'frs-author-name-wrap'}).a.get_text().strip()
57 item.firstTime = tag.find('span', attrs={'title':'创建时间'}).get_text().strip()
58 item.reNum = tag.find('span', attrs={'title':'回复'}).get_text().strip()
59 item.content = tag.find('div',attrs={'class':'threadlist_abs threadlist_abs_onlyline '}).get_text().strip()
60 item.lastAuthor = tag.find('span',attrs={'class':'tb_icon_author_rely j_replyer'}).a.get_text().strip()
61 item.lastTime = tag.find('span', attrs={'title':'最后回复时间'}).get_text().strip()
62 items.append(item)
64 return items
65
66 def pipelines(self, items):
67 fileName = '百度贴吧_权利的游戏.txt'#.encode('utf-8')
68 with codecs.open(fileName, 'w', 'utf-8') as fp:
69 for item in items:
70 try:
71 fp.write('title:%s \t author:%s \t firstTime:%s \r\ncontent:%s \r\n return:%s \r\n lastAuthor:%s \t lastTime:%s \r\n\r\n\r\n\r\n'
72 %(item.title, item.firstAuthor, item.firstTime,item.content, item.reNum, item.lastAuthor, item.lastTime))
73 except Exception as e:
75 else:
77
78 def getResponseContent(self, url):
79 '''这里单独使用一个函数返回页面返回值,是为了后期方便的加入proxy和headers等
80 '''
81 urlList = url.split('=')
83 url = '='.join(urlList)
84 try:
86 except:
88 else:
90 return response.read()
91
92
93 if __name__ == '__main__':
95 GTI = GetTiebaInfo(url)
按照上面的步骤,在项目中重新建立一个名为mylog.py的PyDev Module(也可以是一个单纯的File)。
mylog.py的内容如下:
1 #!/usr/bin/env python3
2 # -*- coding:utf-8 -*-
3 #Author :hstking
5 #Ctime :2015/09/15
6 #Mtime :
7 #Version :
8
9 import logging
10 import getpass
11 import sys
12
13
14 #### 定义MyLog类
15 class MyLog(object):
16 #### 类MyLog的构造函数
17 def __init__(self):
18 self.user = getpass.getuser()
19 self.logger = logging.getLogger(self.user)
21
22 #### 日志文件名
23 self.logFile = sys.argv[0][0:-3] + '.log'
24 self.formatter = logging.Formatter('%(asctime)-12s %(levelname)-8s %(name)-10s %(message)-12s\r\n')
25
26 #### 日志显示到屏幕上并输出到日志文件内
27 self.logHand = logging.FileHandler(self.logFile, encoding='utf8')
28 self.logHand.setFormatter(self.formatter)
29 self.logHand.setLevel(logging.DEBUG)
30
31 self.logHandSt = logging.StreamHandler()
32 self.logHandSt.setFormatter(self.formatter)
33 self.logHandSt.setLevel(logging.DEBUG)
34
37
38 #### 日志的5个级别对应以下的5个函数
39 def debug(self,msg):
41
42 def info(self,msg):
44
45 def warn(self,msg):
47
48 def error(self,msg):
50
51 def critical(self,msg):
53
54 if __name__ == '__main__':
55 mylog = MyLog()
56 mylog.debug(u"I'm debug 测试中文")
57 mylog.info("I'm info")
58 mylog.warn("I'm warn")
59 mylog.error(u"I'm error 测试中文")
60 mylog.critical("I'm critical")
项目代码已经完成了。此时Eclipse中的项目如图8所示。
图8 Eclipse项目baiduBS4
单击菜单栏上的运行图标,程序运行完毕后单击baiduBS4项目图标,按F5键刷新。得到的结果如图9所示。
图9 Eclipse运行结果
图10 笔记本打开文件
这是因为“百度贴吧_权利的游戏.txt”文件中数据保存的是utf8编码。Eclipse自带的文字编辑器默认支持的是GBK编码,所以会显示乱码。而Windows记事本notepad虽然也默认支持的是GBK,但是它同时也支持utf8编码。
3、代码分析
在项目baiduBS4中除了主程序外,还自定义了一个mylog.py模块。这个模块的作用很明显,就是为了主程序提供log功能。
第27~36行则定义了两个loghandler。一个是将log输出到文本中,一个是将log输出到终端方便调试。第39~52行则按照logging模块定义了5个log级别。
主程序getCommentInfo.py也比较简单。第10~14行还是导入所需的模块。在第17~24行定义了一个新类。主程序里的Item类是仿照Scrapy框架中的items.py写的。Scrapy的框架非常方便,也很合理。也可以完全参考Scrapy的方法,重新建立一个Python模块,将这个类放到一个单独的文件中。
第68~76行把得到的items列表写入到最终的数据保存文件“百度贴吧_权利的游戏.txt”中去。其中还添加了一个try语句,防止写入文件失败。
第93~95行是__main__函数,实例化GetTiebaInfo类。
4、Eclipse调试
虽然在Windows下也可以使用pdb模块对Python程序进行调试。Pdb的强大当然是无须质疑,但直观上来说就远远不如Eclipse了。下面就牛刀小试,实验一下Eclipse的调试功能。
首先要做的是在程序中添加断点,也就是程序运行中暂停中断的位置。在所需中断行的最前方,行号的前面空白处双击右键,会出现一个绿色气球的图标,表明断点已经设立成功。这里只在41行和60行设置了2个断点,如图11所示。
图11 Eclipse设置断点
再单击Eclipse上方菜单栏最右边的爬虫图标,进入调试模式。单击图标栏的爬虫图标开始调试。程序运行到断点处会自动停止运行,单击图标栏的箭头图标进行单步调试。在程序栏中的箭头指向运行的位置。可以在变量标签中观察变量的值。测试完毕后可以单击图标栏的停止图标退出调试,如图12所示。
图12 Eclipse调试
配合log模块,即使程序出现什么问题也可以很容易地找到出错的位置,方便修改。
微信公众号:计算机与网络安全
ID:Computer-network
【推荐书籍】
领取专属 10元无门槛券
私享最新 技术干货