zoukankan      html  css  js  c++  java
  • 《学习scrapy框架爬小说》的进一步完善

    一、完善目标:

    1、为方便使用,把小说拼音或英文名,小说输出中文名,第一章节url地址变量化,修改这些参数即可爬取不同的小说。

    2、修改settings.py设置文件,配置为记录debug的log信息,以方便排错。

    3、修改字符集编码,解决部分网页有emoji符号,导致无法把爬取的网页内容存入数据表的问题。(如:http://www.xbiquge.la/43/43474/19425972.html页面出现了emoji符号)

    二、实施过程

    1、修改pipelines.py文件:

    (python) [root@localhost xbiquge]# vi xbiquge/pipelines.py
            self.url_firstchapter = "http://www.xbiquge.la/43/43474/19425971.html"  #此处为小说的第一章节链接地址。
    # -*- coding: utf-8 -*-

    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
    import os
    import time
    import pymysql
    from twisted.enterprise import adbapi
    from pymysql import cursors

    class XbiqugePipeline(object):
        #定义类初始化动作,包括连接数据库novels及建表
        def __init__(self):
            dbparams = {
                'host':'127.0.0.1',
                'port':3306,
                'user':'root',
                'password':'password',
                'database':'novels',
                'charset':'utf8mb4'   #使用utf8mb4字符集可避免emoji表情符号无法存入数据表的错误,这是因为mysql的utf8只支持3个字节的存储,而一般字符是3个字节,但是emoji表情符号是4字节。(参见:《MySQL插入emoji表情错误的3种解决方案,Incorrect string value: 'xF0x9Fx98x84'》https://blog.csdn.net/dmw412724/article/details/81119325)

            }
            self.conn = pymysql.connect(**dbparams)
            self.cursor = self.conn.cursor()
            self._sql = None
            self.name_novel = "heifen"   #此处为小说的英文或拼音名,此名也是小说存储表文件名。
            self.url_firstchapter = "http://www.xbiquge.la/43/43474/19425948.html"  #此处为小说的第一章节链接地址。
            self.name_txt = "老婆的头号黑粉"   #此处为小说的中文名称,输出文件以此命名。

        #爬虫开始
        def open_spider(self,spider):
            self.createtable()  #爬虫开始时先初始化小说存储表
            return

        #建表
        def createtable(self):
            self.cursor.execute("drop table if exists "+ self.name_novel)
            self.cursor.execute("create table " + self.name_novel + " (id int unsigned auto_increment not null primary key, url varchar(50) not null, preview_page varchar(50), next_page varchar(50), content TEXT not null) charset=utf8mb4")
            return

        def process_item(self, item, spider):
            self.cursor.execute(self.sql, (item['url'], item['preview_page'], item['next_page'], item['content']))
            self.conn.commit()
            return item

        @property
        def sql(self):
            if not self._sql:
                self._sql = """
                    insert into """ + self.name_novel + """(id, url, preview_page, next_page, content) values(null, %s, %s, %s, %s)
                    """
                return self._sql
            return self._sql

        #从数据库取小说章节内容写入txt文件
        def content2txt(self):
            self.cursor.execute("select count(*) from " + self.name_novel)
            record_num = self.cursor.fetchall()[0][0]
            print(record_num)
            counts=record_num
            url_c = """+self.url_firstchapter+"""
            start_time=time.time()  #获取提取小说内容程序运行的起始时间
            f = open(self.name_txt+".txt", mode='w', encoding='utf-8')   #写方式打开小说名称加txt组成的文件
            for i in range(counts):
                sql_c = "select content from " + self.name_novel + " where url=" + url_c  #组合获取小说章节内容的sql命令。此处需要修改数据库文件名称
                self.cursor.execute(sql_c)
                record_content_c2a0=self.cursor.fetchall()[0][0]  #获取小说章节内容
                record_content=record_content_c2a0.replace(u'xa0', u'')  #消除特殊字符xc2xa0
                f.write(' ')
                f.write(record_content + ' ')
                f.write(' ')
                sql_n = "select next_page from " + self.name_novel + " where url=" + url_c   #组合获取下一章链接的sql命令。此处需要修改数据库文件名称
                self.cursor.execute(sql_n)
                url_c = """ + self.cursor.fetchall()[0][0] + """  #下一章链接地址赋值给url_c,准备下一次循环。
            f.close()
            print(time.time()-start_time)
            print(self.name_txt + ".txt" + " 文件已生成!")
            return

        #爬虫结束,调用content2txt方法,生成txt文件
        def close_spider(self,spider):
            self.content2txt()
            return

    2、spider文件:

    (python) [root@localhost xbiquge]# vi xbiquge/spiders/heifen.py   #爬虫文件可复制使用,不用再次使用scrapy genspider命令来产生。

    # -*- coding: utf-8 -*-
    import scrapy
    from xbiquge.items import XbiqugeItem

    class SancunSpider(scrapy.Spider):   #此类是由scrapy genspider sancun www.xbiquge.la命令生成,抓取不同小说时,此类名可不用修改。
        name = 'heifen'   #不同的爬虫,此处需要设置不同的名字。
        allowed_domains = ['www.xbiquge.la']
        #start_urls = ['http://www.xbiquge.la/10/10489/']

        def start_requests(self):
            start_urls = ['http://www.xbiquge.la/43/43474/']
            for url in start_urls:
                yield scrapy.Request(url=url, callback=self.parse)

        def parse(self, response):
            dl = response.css('#list dl dd')     #提取章节链接相关信息
            for dd in dl:
                self.url_c = "http://www.xbiquge.la" + dd.css('a::attr(href)').extract()[0]   #组合形成小说的各章节链接
                #print(self.url_c)
                #yield scrapy.Request(self.url_c, callback=self.parse_c,dont_filter=True)
                yield scrapy.Request(self.url_c, callback=self.parse_c)    #以生成器模式(yield)调用parse_c方法获得各章节链接、上一页链接、下一页链接和章
    节内容信息。
                #print(self.url_c)
        def parse_c(self, response):
            item = XbiqugeItem()
            item['url'] = response.url
            item['preview_page'] = "http://www.xbiquge.la" + response.css('div .bottem1 a::attr(href)').extract()[1]
            item['next_page'] = "http://www.xbiquge.la" + response.css('div .bottem1 a::attr(href)').extract()[3]
            title = response.css('.con_top::text').extract()[4]
            contents = response.css('#content::text').extract()
            text=''
            for content in contents:
                text = text + content
            #print(text)
            item['content'] = title + " " + text.replace('15', ' ')    #各章节标题和内容组合成content数据,15是^M的八进制表示,需要替换为换行符。
            yield item     #以生成器模式(yield)输出Item对象的内容给pipelines模块。

    3、修改settings文件:

      (python) [root@localhost xbiquge]# vi xbiquge/settings.py

    ...

    ROBOTSTXT_OBEY = False

    ...

    ITEM_PIPELINES = {
        'xbiquge.pipelines.XbiqugePipeline': 300,
    }

    ...

    FEED_EXPORT_ENCODING = 'utf-8'
    LOG_LEVEL = 'DEBUG'
    LOG_FILE =  './myspiders.log'

    4、items.py文件:

    # -*- coding: utf-8 -*-
    # Define here the models for your scraped items
    #
    # See documentation in:
    # https://docs.scrapy.org/en/latest/topics/items.html
    import scrapy
    class XbiqugeItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        url = scrapy.Field()
        preview_page = scrapy.Field()
        next_page = scrapy.Field()
        content = scrapy.Field()

    三、爬取不同小说的使用方法:

    1、拷贝spider文件:cp heifen.py xueba.py

    2、修改新spider文件中的爬虫名(name)和目录页url地址(start_urls):

    (1)name = 'heifen'  修改为name = 'xueba';

    (2)start_urls = ['http://www.xbiquge.la/43/43474/'] 修改为 start_urls = ['http://www.xbiquge.la/19/19639/']

    3、修改pipelines.py文件中三个变量内容:self.name_novel、self.url_firstchapterself.name_txt

    4、运行爬虫程序(在/root/xbiquge目录下):scrapy runspider  xbiquge/spiders/xueba.py

    运行完成,即可在当前目录下(/root/xbiquge)看到生成的小说txt文件。爬虫运行debug信息可在/root/xbiquge/myspiders.log中查看。

  • 相关阅读:
    HDU 1025 Constructing Roads In JGShining's Kingdom (DP+二分)
    HDU 1158 Employment Planning
    HDU 2059 龟兔赛跑
    Csharp 简单操作Word模板文件
    Csharp windowform datagridview Clipboard TO EXCEL OR FROM EXCEL DATA 保存datagridview所有數據
    Csharp 讀寫文件內容搜索自動彈出 AutoCompleteMode
    Csharp windowform controls clear
    CSS DIV大图片右上角叠加小图片
    Csharp DataGridView自定义添加DateTimePicker控件日期列
    Csharp 打印Word文件默認打印機或選擇打印機設置代碼
  • 原文地址:https://www.cnblogs.com/sfccl/p/12055800.html
Copyright © 2011-2022 走看看