Python爬虫实例--爬取百度贴吧小说
写在前面
本篇文章是我在简书上写的第一篇技术文章,作为一个理科生,能把仅剩的一点文笔拿出来献丑已是不易,希望大家能在指教我的同时给予我一点点鼓励,谢谢。
一.介绍
小说吧:顾名思义,是一个小说爱好者的一个聚集地。当然这不是重点,重点是,我们要做的事情便是将小说吧中以帖子连载形式的小说用爬虫给拿下来保存到本地
这个项目是我曾初学python之时做的一个练习项目,现在再重新拿出来作为一篇开篇简作献给大家。阅读本文不需要有很高的python技术或者爬虫知识,只要略微有些python基础就可以,在一些地方,我会尽量给大家详细备注。
二.环境:
Python版本:Python2.7
IDE:Pycharm2017
第三方库:
urllib2
模块:urllib2
是python的一个获取url(Uniform ResourceLocators,统一资源定址器)的模块。
re
模块:Python 的re
模块(Regular Expression 正则表达式)提供各种正则表达式的匹配操作
注:以上两个第三方库在Python2.7中自带,因此不用再安装。本案例在使用第三方库函数时会详细介绍用法与功能。
三.案例
1.导入模块
首先创建一个python文件,我这里为main.py
(文件名随意取,本案例只使用一个py文件)。本案例中我们使用两个模块urllib2
和re
,因此首先导入模块.
# -*- coding:utf-8 -*-
import urllib2 , re
当然,python2版本需要在开头声明编码格式。除了上述代码的写法以外,也可以这样声明
# coding = utf-8
2.理解思路
我个人在做项目前习惯先分析项目,将步骤一步一步的写出来,然后去慢慢实现。
- 找到目标网页,获取源码
- 匹配标题,获取标题内容
- 匹配正文,获取正文内容
- 去除或者替换杂项
OK,这里思路就是这样的一个四部曲。现在来看一下代码框架。
# -*- coding:utf-8 -*-
import urllib2 , re
#这是本案例的类
class Novel:
baseUrl = '' #这里是你要爬取的小说的链接
#这个方法用来获取网页源码
def getPage(self):
pass
#这个方法用来获取小说标题并保存
def getTitle(self):
pass
#这个方法用来获取小说文本并保存
def getText(self):
pass
#这是一个测试模块,执行本文件时的入口
if __name__ == '__main__':
n = Novel() #实例化一个类
#print n.getPage() #获取网页源码
n.getTitle()#获取小说题目
n.getText() #获取小说内容
现在开始一步步实现功能:
1.找到目标网页,获取网页源码
我在小说吧精品贴里面随便翻了一个帖子,就以这个帖子为案例。
【原创】《贫僧为什么不可以谈恋爱》(古言,长篇)
现在我们需要爬取这个帖子中小说内容,我们需要直接将它的链接地址给baseUrl
吗?当然不是
爬取一个帖子上的小说,实际上是去爬取该小说作者的所发表的内容,所以我们还需要进行一步操作,只看楼主
我们所需要的链接地址,就是当前这个了
https://tieba.baidu.com/p/4973334088?see_lz=1
注意一定是要只看楼主后的链接,比之前的会多出个?see_lz=1
现在就将你得到的链接地址赋值给baseUrl
baseUrl = 'https://tieba.baidu.com/p/4973334088?see_lz=1'
接下来我们来获取这个网页的源码,也就是实现getPage函数:
def getPage(self):
request = urllib2.Request(self.baseUrl)
response = urllib2.urlopen(request).read()
return response
本函数现实通过以基本链接baseUrl
为参数实现了一个Request
请求类的对象request。接着通过urlopen去执行request请求对象打开目标网页。接着通过调用
read`函数获取目标网页的源码,并作为函数返回值返回.
返回的网页源码,可在测试代码块中通过调用输出本函数查看。
例:
if __name__ == '__main__':
n = Novel() #实例化一个类
print n.getPage() #获取网页源码
2.匹配标题,获取标题内容
首先先亮出我的代码:
def getTitle(self):
html = self.getPage() #调用获取源码
#r防止转义
reg = re.compile(r'<h3 class="core_title_txt pull-left text-overflow " title="(.*?)" style=')
items = re.findall(reg,html)
for item in items:
print item
f = open('novel.txt','w')
f.write('标题===>>>'+item)
f.close()
注意:代码错行要在行末加\
号
例如:
print 'hello \
world'
首先我们在网页源码中寻找包含小说主题部分的源码,可以通过Ctrl+F搜索。查找到<div>^=……中间包含小说主题<.div>
这么一长串的包含小说主题的代码。只要将主题部分全部置换为(.*?)号就可以了。
在正则表达式中的含义:
.:匹配任意字符,除了换行符
:匹配前面的子表达式零次或多次
?:匹配前面的子表达式零次或一次
():标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用
(.>):匹配所有满足条件的表达式并作为结果集返回
re.compile
函数是将正则表达式的字符串形式编译为Pattern
实例,然后使用Pattern实例处理文本并获得匹配结果,其中字符串前的r是为了防止转义。
findall(正则表达式,文本) ------将满足的匹配结果以list列表返回
用迭代拿到items中的主题名后在将之写入名为novel.txt
的文件中
3.匹配正文,获取小说正文内容
匹配正文,与匹配标题相差无几,首先是寻找以楼主发表的第一层为例的代码<div>
段,从中获取可以作为正则匹配的语句。并将正文部分改为(.*?)
如下
class="d_post_content j_d_post_content "> (.*?)</div><br>
实现函数如下:
#这个方法用来获取小说文本并保存
def getText(self):
html = self.getPage()
reg = re.compile(r'class="d_post_content j_d_post_content "> (.*?)</div><br>',re.S)#匹配换行符
req = re.findall(reg,html)
for i in req:
print i
f = open('novel.txt','a') #a 追加模式
f.write('\n'+i)
f.close()
如同匹配主题一样的步骤匹配正文,但是并没有结束,因为你会在你的结果中看到这样
对没错。杂乱无章的正文,中间还有HTML
中的<a>
,<img>
,<br>
等标签
我们接着来处理
4.替换或者去出杂项
re
模块中有sub
函数
sub(被替换的内容,替换的内容,需要处理的文本) ---- 返回处理后的文本
现在我们将杂项全部给替换成空字符吧""
吧
当然<br>
标签可以直接调用字符串中的replace
函数替换成换行符\n
修改后的函数模块如下:
def getText(self):
html = self.getPage()
reg = re.compile(r'class="d_post_content j_d_post_content "> (.*?)</div><br>',re.S)#匹配换行符
req = re.findall(reg,html)
for i in req:
removeA = re.compile('<a.*?>|</a>')
removeIMG = re.compile('<img.*?>')
removeHTTP = re.compile('<http.*?.html>')
i = re.sub(removeA,"",i)
i = re.sub(removeIMG,"",i)
i = re.sub(removeHTTP,"",i)
i = i.replace('<br>','\n')
print i
f = open('novel.txt','a') #a 追加模式
f.write('\n'+i)
f.close()
注意:记得在打开文件函数中,对文件的操作方式为a
追加模式
案例结束:
将完整代码贴给大家:
# -*- coding: utf-8 -*-
import urllib2 , re
#这是本案例的类
class Novel:
baseUrl = 'https://tieba.baidu.com/p/4973334088?see_lz=1' #这里是你要爬取的小说的链接
#这个方法用来获取网页源码
def getPage(self):
request = urllib2.Request(self.baseUrl)
response = urllib2.urlopen(request).read()
return response
#这个方法用来获取小说标题并保存
def getTitle(self):
html = self.getPage() #调用获取源码
#r防止转义
reg = re.compile(r'<h3 class="core_title_txt pull-left text-overflow " title="(.*?)" style=')
items = re.findall(reg,html)
for item in items:
print item
f = open('novel.txt','w')
f.write('标题===>>>'+item)
f.close()
#这个方法用来获取小说文本并保存
def getText(self):
html = self.getPage()
reg = re.compile(r'class="d_post_content j_d_post_content "> (.*?)</div><br>',re.S)#匹配换行符
req = re.findall(reg,html)
for i in req:
removeA = re.compile('<a.*?>|</a>')
removeIMG = re.compile('<img.*?>')
removeHTTP = re.compile('<http.*?.html>')
i = re.sub(removeA,"",i)
i = re.sub(removeIMG,"",i)
i = re.sub(removeHTTP,"",i)
i = i.replace('<br>','\n')
print i
f = open('novel.txt','a') #a 追加模式
f.write('\n'+i)
f.close()
#这是一个测试代码块,执行本文件时的入口
if __name__ == '__main__':
n = Novel() #实例化一个类
#print n.getPage() #获取网页源码
n.getTitle()#获取小说题目
n.getText() #获取小说内容
以后想要获取小说吧哪个小说,只要将baseUrl
的地址修改一下就好咯。
撒花撒花撒花,从11点写到了将近2点,终于搞定了。
因为是第一次写技术文写这么长时间,所以,,后面耐心不太好,导致后半篇文章质量太差劲。
不过,终究是先搞完了一篇哪,简书处女技术作。。
至于文章瑕疵,我在白天会花时间去修改,也希望大家给我多多提意见。我呢~争取展现给大家的是一篇更加完美的文章。
夜了,晚安。
看在作者君这么辛苦的份上,求您点个喜欢吧!!