记念个人第一个完整的小说爬虫

记念个人第一个爬虫程序,一共写了三个白天,其中有两个上午没有看,中途遇到了各类奇怪的问题,伴随着他们的解决,对于一些基本的操做也弄清楚了。果真,对于这些东西的最号的学习方式,就是在使用中学习,经过解决问题的方式来搞定这些知识。按需索取,才能更有针对性。html

大致记录下整个过程。python


准备构思

出于对于python的热爱,想要尝试一些练手的项目,可是不管是看书,仍是直接尝试别人的项目,到最后都会沦为不停地复制粘贴...最实际的就是本身来上手亲自写代码。思路都是同样的,可是具体的实现还得靠本身。正则表达式

之前的复制粘贴给个人帮助也就是告诉了我大体的流程。express

肯定目标网址

目标网址是关键。我梦想中的爬虫是那种偏向于更智能的,直接给他一个想要获取的关键词,一步步的流程直接本身完成,能够本身给定范围,也能够直接爬取整个互联网或者更实际的就是整个百度上的内容,可是,目前就我而言,见到的爬虫,都是给定目标网址,经过目标页面上的内容进一步执行规定的操做,因此如今来看,咱们在写爬虫以前,须要肯定一个基准页面,这个是须要咱们事先制定的。在考虑咱们须要程序完成怎样的功能,获取页面文本仍是相关连接内容仍是其余的目的。编程

我这个程序想要获取的是《剑来》小说,把各个章节的内容爬去下载存储到文件里。浏览器

编程只是实现目的的工具。安全

因此重点是分析咱们的需求。python爬虫

获取小说目录页面是基本。这里有各个章节的连接,标题等等内容。这是咱们须要的。socket

有了各个章节的连接,就须要进入其中得到各个章节的内容。工具

因此,咱们须要得到页面内容,须要从中得到目标内容。

因此使用 urllib.requestre 库。

前者用来得到网页内容,后者得到目标信息。

headers

直接使用urllib.requesturlopen()read()方法是会报相似如下的错误(这里是网上查找过来的,都是相似的):

raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 403: Forbidden

出现urllib2.HTTPError: HTTP Error 403: Forbidden错误是因为网站禁止爬虫,能够在请求加上头信息,假装成浏览器。

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0'}
request = url_req.Request(url, headers=headers)
response = url_req.urlopen(request, data=None, timeout=3)
html = response.read().decode('GBK')

注意:这里存在两个容易出问题的地方。

  • 编码:编码问题是使用爬虫中有时候会很头痛的问题,因为网页源代码编码格式不明确,因此这里尝试了许久。

使用chardet库的detect()方法能够检测字节字符串的编码。因此直接检测这里的html(先不要解码)。输出的是GB2312,可是在后面页面的爬取中,会出现提示有的字符的编码异常,因此这里采起了比其范围更广的中文字符集GBK,解决了这个问题。

  • 设置超时范围:因为频繁的获取网页内容,目标网站有时候会出现没有响应的问题。

(这个问题能够见我在CSDN上的提问:关于python爬虫程序中途中止的问题

因而我采起了捕获 urlopen()socket.timeout异常,并在出现异常的时候再循环访问,直到得到目标页面。

得到目标内容

这里使用的是正则表达式。re模块。这里的使用并不复杂。

首先须要一个模式字符串。以re.I指定忽略大小写,编译后的对象拥有自己匹配的方法,这里使用的是findall(),返回一个全部结果组成的列表。能够及时返回输出其内容,进而选择合适的部分进行处理。

python 正则表达式

经过查看相关的符号,这里使用(.+?)来实现匹配非贪婪模式(尽可能少的)下任意无限字符,对之使用(),进而匹配括号内的模式。

文件写入

使用with open() as file:,进而能够处理文件。而且能够自动执行打开和关闭文件,更为便捷安全。

with open(findall_title[0] + '.txt', 'w+', encoding='utf-8') as open_file:
  • 这里也要注意编码的问题,指定utf-8。会避免一些问题。
  • 这里使用w+模式,追加写文件。

完整代码

# -*- coding: utf-8 -*-
"""
Created on Fri Aug 11 16:31:42 2017
@author: lart
"""

import urllib.request as url_req
import re, socket, time


def r_o_html(url):
    print('r_o_html begin')

    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0'}

    request = url_req.Request(url, headers=headers)

    NET_STATUS = False
    while not NET_STATUS:
        try:
            response = url_req.urlopen(request, data=None, timeout=3)
            html = response.read().decode('GBK')
            print('NET_STATUS is good')
            print('r_o_html end')
            return html
        except socket.timeout:
            print('NET_STATUS is not good')
            NET_STATUS = False

def re_findall(re_string, operation, html):

    print('re_findall begin')
    pattern = re.compile(re_string, re.I)

    if operation == 'findall':
        result = pattern.findall(html)
    else:
        print('this operation is invalid')
        exit(-1)

    print('re_findall end')
    return result


if __name__ == '__main__':
    url_base = 'http://www.7kankan.la/book/1/'

    html = r_o_html(url_base)

    findall_title = re_findall(r'<title>(.+?)</title>', 'findall', html)

    findall_chapter = re_findall(r'<dd class="col-md-3"><a href=[\',"](.+?)[\',"] title=[\',"](.+?)[\',"]>', 'findall', html)

    with open(findall_title[0] + '.txt', 'w+', encoding='utf-8') as open_file:
        print('article文件打开', findall_chapter)
        for i in range(len(findall_chapter)):
            print('第' + str(i) + '章')

            open_file.write('\n\n\t' + findall_chapter[i][1] + '\n --------------------------------------------------------------------- \n')

            url_chapter = url_base + findall_chapter[i][0]

            html_chapter = r_o_html(url_chapter)

            findall_article = re_findall(r'&nbsp;&nbsp;&nbsp;&nbsp;(.+?)<br />', 'findall', html_chapter)

            findall_article_next = findall_chapter[i][0].replace('.html', '_2.html')

            url_nextchapter = url_base + findall_article_next

            html_nextchapter = r_o_html(url_nextchapter)

            if html_nextchapter:
                findall_article.extend(re_findall(r'&nbsp;&nbsp;&nbsp;&nbsp;(.+?)<br />', 'findall', html_nextchapter))

                for text in findall_article:
                    open_file.write(text + '\n')

            time.sleep(1)

    print('文件写入完毕')
相关文章
相关标签/搜索