python 运用requests库 以及 正则表达式 爬取小说实例以及心得

笔者标注部分:

笔者技艺不精,若文章中有错误之处,还望各位大佬海涵,笔者希望与大家共同进步
此外笔者推荐python3以上的编辑器,因为过程中会出现一些编码问题,python2系列可能会将问题复杂化,
笔者采用python3.6进行演示
爬取网站内容:某网站小说(至于哪个网站,自行看代码)
robots协议:人工查看,无robots协议,可合法的对网站的爬取(若您对robots协议不熟悉,可询问小杜)
整体过程是,我们先通过requests库,得到网页源代码,再通过re(正则表达式)的筛选得到文章,
然后循环写入txt文件中。
废话不多说,我们直接开始。

# 笔者采用了pycharm来进行脚本的编写

如您未安装requests库,可在终端输入pip install requests(如下图),pycharm还有其它方法导入requests库,笔者在此不展开讨论。

因为re(正则表达式是python库中内置的,所以无需安装)


首先我们导入requests库和re库


(貌似python3以上默认utf-8编码,博主还未尝试,在此直接加上coding)

(A)然后我们定义一个函数叫 get_html 用于接收url,返回网页源代码



我们在浏览器中右键查看小说网页页面的源代码,我们观察到小说封装在<br />标签中

头:

                  

尾:

                 (大家关注标签<br />就好,小说内容,嗯,忽略)

有图有真相,小说内容封装在<br />中,这是我们能通过正则表达式筛选出小说文本的前提。

(B)下一步定义一个函数叫get_novel对返回的demo(网页源码文本)用re进行筛选


注释截图截不下,加在下面:

fp = open('我不喜欢这个世界,我只喜欢你.txt', 'a')
# a 表示追加  也就是写完一篇文档后,下一篇追加在已写的文字下面,如果用 w 则会清除前面内容再写入
lst = re.findall('<br />.*<br />', demo, re.S)


re.findall方法匹配所有内容,返回一个list我放到lst中."<br />.*<br />",小说封装在<br />标签中,' .* '(点星)表示任意内容(就是表示小说的内容)。

当然这还没有完事,lst中元素,也就是我们得到的小说中还有众多标签对,会影响我们的正常阅读,所以我们要干掉这些标签,

我们用replace方法用 空 (‘’),来取代这些标签(如<p>)

for item in lst:
    fp.write(item.replace(u'\xa0', u' ').replace('<p>', '').
             replace('</p>', '').replace('<br />', ''))

在这里笔者遇到个麻烦事 就是gbk 和 \xa0 的编码问题,所以通过replace替换

打开文件一定不要忘记关闭哦。

fp.close()

这只是爬取了一个页面,我们需要在该页面中得到下一章的url。笔者在网站页面上观察到该网站采用上一章以及下一章进行翻页,这里会出现一个小问题,现在先留着,一会我们再聊这个问题

(C)下一步我们定义一个cycle_spider

def cycle_spider(url):
    # 获取下一页面的地址
    demo = get_html(url)
    lst = re.findall(r'http://www.136book.com/wobuxihuanzheshijiewozhixihuanni/fev.*?/', demo)
    for item in lst:
        if item != url:
            url = item
    return url

注释如下:

lst = re.findall(r'http://www.136book.com/wobuxihuanzheshijiewozhixihuanni/fev.*?/', demo)

笔者在网页源代码中发现,小说url 到/fev 之前是完全一致的,也就是说,我让‘  .*?  ’表示fev之后的部分可以高精度的匹配出url,但问题来了,第一页只有下一页,最后一页只有上一页,中间的既有上一页和下一页,也就是说, lst中(re.findall返回值是个list)有一个或者是两个。如,第一页,你需要调用第二页的url,你需要用lst[0],而第二页要调用第三页url就需要用lst[1],第三页与第四页的关系也是lst[1].为防止提取到前一页的url,我们用以下函数:

for item in lst:
    if item != url:
        url = item

然后笔者希望通过一个函数来对接以上定义函数的接口

(D)定义一个名为finish的函数:

def finish():
    url = 'http://www.136book.com/wobuxihuanzheshijiewozhixihuanni/fevjf/'
    last_page = input('请输入最后一章的页码:')
    for _ in range(1, int(last_page)):
        get_novel(url)
        print("loading ....")
        url = cycle_spider(url)
        print('正在拷贝第{}页'.format(_))

这里要手工查看一下一共有多少章 (last_page),当然肯定还有其他方法能让爬虫更一步的自主,但笔者认为手工查看也不失为一种好办法。(笔者输入的是24,实际为23章,但大家对python的左闭右开很了解,换一种说法24 - 1 = 23嘛)

然后最后一步

调用finish函数启动爬虫

finish()

然后爬虫就开始工作了


该方法普适性强,但各网站源代码格式有所差异,笔者不敢说都能依次类推,但希望能为大家提供一种方法。

我喜欢这个世界,我也喜欢你

附赠笔者成果,以及部分参考文献,祝大家新年快乐

链接:https://pan.baidu.com/s/1dJ3Yeq 密码:h3v1

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值