7

小说站爬虫全记录 – 提取TXT小说

 4 years ago
source link: https://www.taterli.com/6227/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

第一步,爬取并入库MySQL,这一步占了最多的时间,为了避免被Anti-Spider机制影响,所以限速也较低.

iamyY3Q.png!web

因为URL格式里面似乎包含了ID信息,所以也一并采集了.

2YRn6fI.png!web

第一段ID似乎是小说ID,第二段ID似乎是章节ID,章节ID和小说ID并非连续,但是同样的小说ID下,章节ID必然递增存在,所以储存时候就这么干.(正文内容省略)

bIBzInm.png!web

第二步就是得到CSV文件(大约100GB),然后从CSV文件入库,为什么不用pipeline入库的原因是数据库是临时用的,按需付费省着用.

CREATE DATABASE `books`
use books;
DROP TABLE `scrapy`;
CREATE TABLE `scrapy` (
`id` INT NOT NULL AUTO_INCREMENT,
`id_primary` INT NOT NULL,
`id_subset` INT NOT NULL,
`title` VARCHAR(200) NOT NULL DEFAULT '',
`chapter_name` VARCHAR(200) NOT NULL DEFAULT '',
`chapter_content` MEDIUMTEXT,
`created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
PRIMARY KEY (`id`),
INDEX `id_subset` (`id_subset`),
INDEX `id_primary` (`id_primary`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
LOAD DATA LOCAL INFILE '/mnt/ScrapyBooks.csv' IGNORE INTO TABLE scrapy CHARACTER SET utf8mb4 FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n' IGNORE 1 LINES (`chapter_content`,`chapter_name`,`id_primary`,`id_subset`,`title`);
SHOW WARNINGS;

如果采集到的CSV 100G的话,入库大概需要170G的数据库空间,另外CSV文件需要处理,否则会被意外截断,前面已经有文章说过.

CSV导入MySQL数据库被意外截断解决

导入成功的最佳结果当然是0错误,0警告了.

QJZnMrZ.png!web

第三步就是从数据库再提取回来,生成TXT文本的小说,当然,都入库了也可以用来生成网站.

import pymysql

def make( id ):
    cursor = db.cursor()
    sql = "SELECT * FROM scrapy WHERE id_primary = " + str(id) + " ORDER BY id_subset ASC"
    cursor.execute(sql)

    result = cursor.fetchone()
    
    if result[3] == "":
        print('似乎出现了书名不正确的情况')
        print(result)
        return

    print('正在写入 ' + result[3] + '.txt')
    wf = open('/mnt/volume_fra1_02/books/' + result[3] + '.txt','a')

    #至少先做第一次提取,写入标题,然后检测标题是否在正文有重复,如果有重复,删除正文标题.
    wf.write(result[4]+'\r\n')
    content = result[5].replace(result[4],'')
    wf.write(content.strip('"')+'\r\n'+'\r\n')

    while result is not None:
        result = cursor.fetchone()
        if result is not None:
            wf.write(result[4]+'\r\n')
            content = result[5].replace(result[4],'')
            wf.write(content.strip('"')+'\r\n'+'\r\n')

    wf.close()

db = pymysql.connect(host="127.0.0.1",user="root",db="books",cursorclass = pymysql.cursors.SSCursor)

cursor = db.cursor()
sql = "SELECT DISTINCT id_primary FROM scrapy"
cursor.execute(sql)

id_dict = []

result = cursor.fetchone()
id_dict.append(result[0])

while result is not None:
    result = cursor.fetchone()
    if result is not None:
        id_dict.append(result[0])

for tid in id_dict:
    make(tid)

cursor.close()

db.close()

写入数据中…

bayqAbA.png!web

打开检查,发现顺序正确,内容没问题.

第四步,导出的文件总量大小约等于CSV文件大小(可能略大/略小),有些只有几MB,有些几十上百M,抽查发现有些提取出现问题,这个也是因为蜘蛛算法问题,看起来需要一些容错机制才行.

BUG举例:

22iEVff.png!web

导致原因,我用的XPATH提取了第一个ul,但是有些地方目录在第二个ul,所以出错了.

VJva6r2.png!web

b6VjM3M.png!web

第一代含BUG爬虫先结束他,想搞第二代时候再说吧.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK