编写Python脚本抓取网络小说来制作自己的阅读器

你是否苦恼于网上无法下载的“小说在线阅读”内容?或是某些文章的内容让你很有收藏的冲动,却找不到一个下载的链接?是不是有种自己写个程序把全部搞定的冲动?是不是学了 python,想要找点东西大展拳脚,告诉别人“哥可是很牛逼的!”?那就让我们开始吧! 哈哈~
    好吧,我就是最近写 Yii 写多了,想找点东西调剂一下.... = =

本项目以研究为目的,所有版权问题我们都是站在作者的一边,以看盗版小说为目的的读者们请自行面壁!
    说了这么多,我们要做的就是把小说正文的内容从网页上爬下来,我们的研究对象是全本小说网....再次声明,不对任何版权负责....
    一开始先做最基础的内容,就是把某一章的内容抓取下来。

环境:Ubuntu, Python 2.7

    基础知识
    这个程序涉及到的知识点有几个,在这里列出来,不详细讲,有疑问的直接百度会有一堆的。
    1.urllib2 模块的 request 对像来设置 HTTP 请求,包括抓取的 url,和伪装浏览器的代理。然后就是 urlopen 和 read 方法,都很好理解。
    2.chardet 模块,用于检测网页的编码。在网页上抓取数据很容易遇到乱码的问题,为了判断网页是 gtk 编码还是 utf-8 ,所以用 chardet 的 detect 函数进行检测。在用 Windows 的同学可以在这里 http://download.csdn.net/detail/jcjc918/8231371 下载,解压到 python 的 lib 目录下就好。
    3. decode 函数将字符串从某种编码转为 unicode 字符,而 encode 把 unicode 字符转为指定编码格式的字符串。
     4. re 模块正则表达式的应用。search 函数可以找到和正则表达式对应匹配的一项,而 replace 则是把匹配到的字符串替换。

    思路分析:
    我们选取的 url 是 http://www.quanben.com/xiaoshuo/0/910/59302.html,斗罗大陆的第一章。你可以查看网页的源代码,会发现只有一个 content 标签包含了所有章节的内容,所以可以用正则把 content 的标签匹配到,抓取下来。试着把这一部分内容打印出来,会发现很多 <br /> 和 &nbsp,<br /> 要替换成换行符, &nbsp 是网页中的占位符,即空格,替换成空格就好。这样一章的内容就很美观的出来了。完整起见,同样用正则把标题爬下来。

    程序

# -*- coding: utf-8 -*- 

import urllib2
import re
import chardet 

class Book_Spider: 

  def __init__(self):
    self.pages = [] 

  # 抓取一个章节
  def GetPage(self):
    myUrl = "http://www.quanben.com/xiaoshuo/0/910/59302.html";
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers = { 'User-Agent' : user_agent }
    request = urllib2.Request(myUrl, headers = headers)
    myResponse = urllib2.urlopen(request)
    myPage = myResponse.read() 

    #先检测网页的字符编码,最后统一转为 utf-8
    charset = chardet.detect(myPage)
    charset = charset['encoding']
    if charset == 'utf-8' or charset == 'UTF-8':
      myPage = myPage
    else:
      myPage = myPage.decode('gb2312','ignore').encode('utf-8')
    unicodePage = myPage.decode("utf-8") 

    try:
      #抓取标题
      my_title = re.search('<h1>(.*?)</h1>',unicodePage,re.S)
      my_title = my_title.group(1)
    except:
      print '标题 HTML 变化,请重新分析!'
      return False 

    try:
      #抓取章节内容
      my_content = re.search('<div.*?id="htmlContent" class="contentbox">(.*?)<div',unicodePage,re.S)
      my_content = my_content.group(1)
    except:
      print "内容 HTML 变化,请重新分析!"
      return False 

    #替换正文中的网页代码
    my_content = my_content.replace("<br />","\n")
    my_content = my_content.replace(" "," ") 

    #用字典存储一章的标题和内容
    onePage = {'title':my_title,'content':my_content}
    return onePage 

  # 用于加载章节
  def LoadPage(self):
    try:
      # 获取新的章节
      myPage = self.GetPage() 

      if myPage == False:
        print '抓取失败!'
        return False 

      self.pages.append(myPage)
    except:
      print '无法连接服务器!' 

  #显示一章
  def ShowPage(self,curPage):
      print curPage['title']
      print curPage['content'] 

  def Start(self):
    print u'开始阅读......\n'
    #把这一页加载进来
    self.LoadPage()
    # 如果self的pages数组中存有元素
    if self.pages:
      nowPage = self.pages[0]
      self.ShowPage(nowPage) 

#----------- 程序的入口处 -----------
print u"""
---------------------------------------
  程序:阅读呼叫转移
  版本:0.1
  作者:angryrookie
  日期:2014-07-05
  语言:Python 2.7
  功能:按下回车浏览章节
---------------------------------------
""" 

print u'请按下回车:'
raw_input()
myBook = Book_Spider()
myBook.Start()

程序运行完在我这里可是很好看的,不信请看:^_^

理所当然地,接下来我们要把整本小说都爬下来。首先,我们要把程序从原来的读完一章就结束,改成读完一章之后可以继续进行下一章的阅读。
    注意到每个小说章节的网页下面都有下一页的链接。通过查看网页源代码,稍微整理一下(  不显示了),我们可以看到这一部分的 HTML 是下面这种格式的:

<div id="footlink">
 <script type="text/javascript" charset="utf-8" src="/scripts/style5.js"></script>
 <a href="http://www.quanben.com/xiaoshuo/0/910/59301.html">上一页</a>
 <a href="http://www.quanben.com/xiaoshuo/0/910/">返回目录</a>
 <a href="http://www.quanben.com/xiaoshuo/0/910/59303.html">下一页</a>
</div>

上一页 、返回目录、下一页都在一个 id 为 footlink  的 div 中,如果想要对每个链接进行匹配的话,会抓取到网页上大量的其他链接,但是 footlink 的 div 只有一个啊!我们可以把这个 div 匹配到,抓下来,然后在这个抓下来的 div  里面再匹配 <a> 的链接,这时就只有三个了。只要取最后一个链接就是下一页的 url 的,用这个 url 更新我们抓取的目标 url ,这样就能一直抓到下一页。用户阅读逻辑为每读一个章节后,等待用户输入,如果是 quit 则退出程序,否则显示下一章。

基础知识:
     上一篇的基础知识加上 Python 的 thread 模块.

源代码:

# -*- coding: utf-8 -*- 

import urllib2
import re
import thread
import chardet 

class Book_Spider: 

  def __init__(self):
    self.pages = []
    self.page = 1
    self.flag = True
    self.url = "http://www.quanben.com/xiaoshuo/10/10412/2095096.html" 

  # 将抓取一个章节
  def GetPage(self):
    myUrl = self.url
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers = { 'User-Agent' : user_agent }
    req = urllib2.Request(myUrl, headers = headers)
    myResponse = urllib2.urlopen(req)
    myPage = myResponse.read() 

    charset = chardet.detect(myPage)
    charset = charset['encoding']
    if charset == 'utf-8' or charset == 'UTF-8':
      myPage = myPage
    else:
      myPage = myPage.decode('gb2312','ignore').encode('utf-8')
    unicodePage = myPage.decode("utf-8") 

    # 找出 id="content"的div标记
    try:
      #抓取标题
      my_title = re.search('<h1>(.*?)</h1>',unicodePage,re.S)
      my_title = my_title.group(1)
    except:
      print '标题 HTML 变化,请重新分析!'
      return False 

    try:
      #抓取章节内容
      my_content = re.search('<div.*?id="htmlContent" class="contentbox">(.*?)<div',unicodePage,re.S)
      my_content = my_content.group(1)
    except:
      print "内容 HTML 变化,请重新分析!"
      return False 

    my_content = my_content.replace("<br />","\n")
    my_content = my_content.replace(" "," ") 

    #用字典存储一章的标题和内容
    onePage = {'title':my_title,'content':my_content} 

    try:
      #找到页面下方的连接区域
      foot_link = re.search('<div.*?class="chapter_Turnpage">(.*?)</div>',unicodePage,re.S)
      foot_link = foot_link.group(1)
      #在连接的区域找下一页的连接,根据网页特点为第三个
      nextUrl = re.findall(u'<a.*?href="(.*?)".*?>(.*?)</a>',foot_link,re.S)
      nextUrl = nextUrl[2][0]
      # 更新下一次进行抓取的链接
      self.url = nextUrl
    except:
      print "底部链接变化,请重新分析!"
      return False 

    return onePage 

  # 用于加载章节
  def LoadPage(self):
    while self.flag:
      if(len(self.pages) - self.page < 3):
        try:
          # 获取新的页面
          myPage = self.GetPage() 

          if myPage == False:
            print '抓取失败!'
            self.flag = False 

          self.pages.append(myPage)
        except:
          print '无法连接网页!'
          self.flag = False 

  #显示一章
  def ShowPage(self,curPage):
      print curPage['title']
      print curPage['content']
      print "\n"
      user_input = raw_input("当前是第 %d 章,回车读取下一章或者输入 quit 退出:" % self.page)
      if(user_input == 'quit'):
        self.flag = False
      print "\n" 

  def Start(self):
    print u'开始阅读......\n' 

    # 新建一个线程
    thread.start_new_thread(self.LoadPage,()) 

    # 如果self的page数组中存有元素
    while self.flag:
      if self.page <= len(self.pages):
        nowPage = self.pages[self.page-1]
        self.ShowPage(nowPage)
        self.page += 1 

    print u"本次阅读结束" 

#----------- 程序的入口处 -----------
print u"""
---------------------------------------
  程序:阅读呼叫转移
  版本:0.2
  作者:angryrookie
  日期:2014-07-07
  语言:Python 2.7
  功能:按下回车浏览下一章节
---------------------------------------
""" 

print u'请按下回车:'
raw_input(' ')
myBook = Book_Spider()
myBook.Start()

现在这么多小说阅读器,我们只需要把我们要的小说抓取到本地的 txt 文件里就好了,然后自己选个阅读器看,怎么整都看你了。

其实上个程序我们已经完成了大部分逻辑,我们接下来的改动只需要把抓取到每一章的时候不用显示出来,而是存入 txt 文件之中。另外一个是程序是不断地根据下一页的 Url 进行抓取的,那么什么时候结束呢?注意当到达小说的最后一章时下一页的链接是和返回目录的链接是一样的。所以我们抓取一个网页的时候就把这两个链接拿出来,只要出现两个链接一样的时候,就停止抓取。最后就是我们这个程序不需要多线程了,我们只要一个不断在抓取小说页面的线程就行了。
    不过,小说章节多一点时候,等待完成的时间会有点久。目前就不考虑这么多了,基本功能完成就 OK....

基础知识:前面的基础知识 - 多线程知识 + 文件操作知识。

源代码:

# -*- coding:utf-8 -*- 

import urllib2
import urllib
import re
import thread
import chardet 

class Book_Spider: 

  def __init__(self):
    self.pages = []
    self.page = 1
    self.flag = True
    self.url = "http://www.quanben.com/xiaoshuo/0/910/59302.html" 

  # 将抓取一个章节
  def GetPage(self):
    myUrl = self.url
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers = { 'User-Agent' : user_agent }
    req = urllib2.Request(myUrl, headers = headers)
    myResponse = urllib2.urlopen(req)
    myPage = myResponse.read() 

    charset = chardet.detect(myPage)
    charset = charset['encoding']
    if charset == 'utf-8' or charset == 'UTF-8':
      myPage = myPage
    else:
      myPage = myPage.decode('gb2312','ignore').encode('utf-8')
    unicodePage = myPage.decode("utf-8") 

    # 找出 id="content"的div标记
    try:
      #抓取标题
      my_title = re.search('<h1>(.*?)</h1>',unicodePage,re.S)
      my_title = my_title.group(1)
    except:
      print '标题 HTML 变化,请重新分析!'
      return False 

    try:
      #抓取章节内容
      my_content = re.search('<div.*?id="htmlContent" class="contentbox">(.*?)<div',unicodePage,re.S)
      my_content = my_content.group(1)
    except:
      print "内容 HTML 变化,请重新分析!"
      return False 

    my_content = my_content.replace("<br />","\n")
    my_content = my_content.replace(" "," ") 

    #用字典存储一章的标题和内容
    onePage = {'title':my_title,'content':my_content} 

    try:
      #找到页面下方的连接区域
      foot_link = re.search('<div.*?class="chapter_Turnpage">(.*?)</div>',unicodePage,re.S)
      foot_link = foot_link.group(1)
      #在连接的区域找下一页的连接,根据网页特点为第三个
      nextUrl = re.findall(u'<a.*?href="(.*?)".*?>(.*?)</a>',foot_link,re.S)
      #目录链接
      dir_url = nextUrl[1][0]
      nextUrl = nextUrl[2][0]
      # 更新下一次进行抓取的链接
      self.url = nextUrl 

      if(dir_url == nextUrl):
        self.flag = False 

      return onePage
    except:
      print "底部链接变化,请重新分析!"
      return False 

  # 用于加载章节
  def downloadPage(self): 

    f_txt = open(u"斗罗大陆.txt",'w+')
    while self.flag:
      try:
        # 获取新的页面
        myPage = self.GetPage() 

        if myPage == False:
            print '抓取失败!'
            self.flag = False 

        title = myPage['title'].encode('utf-8')
        content = myPage['content'].encode('utf-8') 

        f_txt.write(title + '\n\n')
        f_txt.write(content)
        f_txt.write('\n\n\n') 

        print "已下载 ",myPage['title'] 

      except:
        print '无法连接服务器!'
        self.flag = False 

    f_txt.close() 

  def Start(self):
    print u'开始下载......\n' 

    self.downloadPage() 

    print u"下载完成" 

#----------- 程序的入口处 -----------
print u"""
---------------------------------------
  程序:阅读呼叫转移
  版本:0.3
  作者:angryrookie
  日期:2014-07-08
  语言:Python 2.7
  功能:按下回车开始下载
---------------------------------------
""" 

print u'请按下回车:'
raw_input(' ')
myBook = Book_Spider()
myBook.Start()

(0)

相关推荐

  • Python+Wordpress制作小说站

    我用Python和Wordpress建了一个小说站. 下面主要讲一讲搭建过程中所用的技术.主要分为以下几个部分: Wordpress主题的选取 小说内容的完善 站点的部署 微信公众平台的搭建 1.Wordpress主题的选取 由于自己对php代码编写不是非常熟悉,直接编写网站很可能会遇到各种安全漏洞.对比目前比较流行的博客框架wordpress.joomla.drupal,最终还是选择受众比较广的wordpress.之后选取了一套小说模板,就这么上马啦~~ 2.小说内容的完善 2.1 数据的抓取

  • Python实现的飞速中文网小说下载脚本

    1.JavaScript 加密什么的最讨厌了 :-( 1).eval 一个不依赖外部变量的函数立即调用很天真,看我 nodejs 来干掉你! 2).HTTP 请求的验证首先尝试 Referer,「小甜饼」没有想像中的那么重要. 3).curl 和各命令行工具处理起文本很顺手呢 4).但是 Python 也没多几行呢 2.Requests效率比 lxml 自己那个好太多 3.progressbar太先进了,我还是自个儿写吧-- 4.argparse写 Python 命令行程序必备啊- 5.stri

  • 用python写的一个wordpress的采集程序

    在学习python的过程中,经过不断的尝试及努力,终于完成了第一个像样的python程序,虽然还有很多需要优化的地方,但是目前基本上实现了我所要求的功能,先贴一下程序代码: 具体代码如下: #! /usr/bin/python import os,urllib2,re,time,MySQLdb,sys reTitle = re.compile('<font[^>]*>(.*?)<\/font><font[^>]*') reNeiron = re.compile('

  • Python制作爬虫采集小说

    开发工具:python3.4 操作系统:win8 主要功能:去指定小说网页爬小说目录,按章节保存到本地,并将爬过的网页保存到本地配置文件. 被爬网站:http://www.cishuge.com/ 小说名称:灵棺夜行 代码出处:本人亲自码的 import urllib.request import http.cookiejar import socket import time import re timeout = 20 socket.setdefaulttimeout(timeout) sl

  • Python实现爬取逐浪小说的方法

    本文实例讲述了Python实现爬取逐浪小说的方法.分享给大家供大家参考.具体分析如下: 本人喜欢在网上看小说,一直使用的是小说下载阅读器,可以自动从网上下载想看的小说到本地,比较方便.最近在学习Python的爬虫,受此启发,突然就想到写一个爬取小说内容的脚本玩玩.于是,通过在逐浪上面分析源代码,找出结构特点之后,写了一个可以爬取逐浪上小说内容的脚本. 具体实现功能如下:输入小说目录页的url之后,脚本会自动分析目录页,提取小说的章节名和章节链接地址.然后再从章节链接地址逐个提取章节内容.现阶段只

  • 编写Python脚本抓取网络小说来制作自己的阅读器

    你是否苦恼于网上无法下载的"小说在线阅读"内容?或是某些文章的内容让你很有收藏的冲动,却找不到一个下载的链接?是不是有种自己写个程序把全部搞定的冲动?是不是学了 python,想要找点东西大展拳脚,告诉别人"哥可是很牛逼的!"?那就让我们开始吧! 哈哈~     好吧,我就是最近写 Yii 写多了,想找点东西调剂一下.... = = 本项目以研究为目的,所有版权问题我们都是站在作者的一边,以看盗版小说为目的的读者们请自行面壁!     说了这么多,我们要做的就是把小

  • 编写Python爬虫抓取豆瓣电影TOP100及用户头像的方法

    抓取豆瓣电影TOP100 一.分析豆瓣top页面,构建程序结构 1.首先打开网页http://movie.douban.com/top250?start,也就是top页面 然后试着点击到top100的页面,注意带top100的链接依次为 http://movie.douban.com/top250?start=0 http://movie.douban.com/top250?start=25 http://movie.douban.com/top250?start=50 http://movie

  • 编写Python爬虫抓取暴走漫画上gif图片的实例分享

    本文要介绍的爬虫是抓取暴走漫画上的GIF趣图,方便离线观看.爬虫用的是python3.3开发的,主要用到了urllib.request和BeautifulSoup模块. urllib模块提供了从万维网中获取数据的高层接口,当我们用urlopen()打开一个URL时,就相当于我们用Python内建的open()打开一个文件.但不同的是,前者接收一个URL作为参数,并且没有办法对打开的文件流进行seek操作(从底层的角度看,因为实际上操作的是socket,所以理所当然地没办法进行seek操作),而后

  • Python爬虫抓取技术的一些经验

    前言 web是一个开放的平台,这也奠定了web从90年代初诞生直至今日将近30年来蓬勃的发展.然而,正所谓成也萧何败也萧何,开放的特性.搜索引擎以及简单易学的html.css技术使得web成为了互联网领域里最为流行和成熟的信息传播媒介:但如今作为商业化软件,web这个平台上的内容信息的版权却毫无保证,因为相比软件客户端而言,你的网页中的内容可以被很低成本.很低的技术门槛实现出的一些抓取程序获取到,这也就是这一系列文章将要探讨的话题-- 网络爬虫 . 有很多人认为web应当始终遵循开放的精神,呈现

  • Python如何抓取天猫商品详细信息及交易记录

    本文实例为大家分享了Python抓取天猫商品详细信息及交易记录的具体代码,供大家参考,具体内容如下 一.搭建Python环境 本帖使用的是Python 2.7 涉及到的模块:spynner, scrapy, bs4, pymmssql 二.要获取的天猫数据 三.数据抓取流程 四.源代码 #coding:utf-8 import spynner from scrapy.selector import Selector from bs4 import BeautifulSoup import ran

  • Python实现抓取HTML网页并以PDF文件形式保存的方法

    本文实例讲述了Python实现抓取HTML网页并以PDF文件形式保存的方法.分享给大家供大家参考,具体如下: 一.前言 今天介绍将HTML网页抓取下来,然后以PDF保存,废话不多说直接进入教程. 今天的例子以廖雪峰老师的Python教程网站为例:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000 二.准备工作 1. PyPDF2的安装使用(用来合并PDF): PyPDF2版本:1.2

  • python数据抓取3种方法总结

    三种数据抓取的方法 正则表达式(re库) BeautifulSoup(bs4) lxml *利用之前构建的下载网页函数,获取目标网页的html,我们以https://guojiadiqu.bmcx.com/AFG__guojiayudiqu/为例,获取html. from get_html import download url = 'https://guojiadiqu.bmcx.com/AFG__guojiayudiqu/' page_content = download(url) *假设我

  • python爬虫抓取时常见的小问题总结

    目录 01 无法正常显示中文? 解决方法 02 加密问题 03 获取不到网页的全部代码? 04 点击下一页时网页网页不变 05 文本节点问题 06 如何快速找到提取数据? 07 获取标签中的数据 08 去除指定内容 09 转化为字符串类型 10 滥用遍历文档树 11 数据库保存问题 12 爬虫采集遇到的墙问题 逃避IP识别 变换请求内容 降低访问频率 慢速攻击判别 13 验证码问题 正向破解 逆向破解 前言: 现在写爬虫,入门已经不是一件门槛很高的事情了,网上教程一大把,但很多爬虫新手在爬取数据

  • Python正则抓取网易新闻的方法示例

    本文实例讲述了Python正则抓取网易新闻的方法.分享给大家供大家参考,具体如下: 自己写了些关于抓取网易新闻的爬虫,发现其网页源代码与网页的评论根本就对不上,所以,采用了抓包工具得到了其评论的隐藏地址(每个浏览器都有自己的抓包工具,都可以用来分析网站) 如果仔细观察的话就会发现,有一个特殊的,那么这个就是自己想要的了 然后打开链接就可以找到相关的评论内容了.(下图为第一页内容) 接下来就是代码了(也照着大神的改改写写了). #coding=utf-8 import urllib2 import

  • Python正则抓取新闻标题和链接的方法示例

    本文实例讲述了Python正则抓取新闻标题和链接的方法.分享给大家供大家参考,具体如下: #-*-coding:utf-8-*- import re from urllib import urlretrieve from urllib import urlopen #获取网页信息 doc = urlopen("http://www.itongji.cn/news/").read() #自己找的一个大数据的新闻网站 #抓取新闻标题和链接 def extract_title(info):

随机推荐