一、目标地址:www.23us.so/

二、准备工作 1.开发环境 MacOS + PyCharm + Python3.5.3 + Scrapy + MySQL 2.安装Scrapy和MySQL自行解决

三、开始建项目和编写爬虫 在终端新建scrapy项目

scrapy startproject dingdian
复制代码
  • 因为我们要将数据保存到MySQL数据库中,所以在这里需要自定义MySQL的Pipeline,用PyCharm打开项目,在项目文件夹中新建一个python模块‘mysqlpipelines’,区分框架自带的Pipeline。
  • 在spiders文件夹下创建我们自己的spider(dingdian)
  • 新建一个run.py文件,用作运行爬虫的入口

run.py的内容,'dingdian'是spider的唯一名称,在定义spider的时候定义

from scrapy.cmdline import executeexecute(['scrapy', 'crawl', 'dingdian'])
复制代码

项目结构

建立模型item,在items.py中写入

import scrapyclass DingdianItem(scrapy.Item):# define the fields for your item here like:name = scrapy.Field()author = scrapy.Field()novelurl = scrapy.Field()# 状态serialstatus = scrapy.Field()# 字数serialnumber = scrapy.Field()# 类别category = scrapy.Field()# 编号name_id = scrapy.Field()class DcontentItem(scrapy.Item):# 小说编号id_name = scrapy.Field()# 章节内容chaptercontent = scrapy.Field()# 用于绑定章节顺序num = scrapy.Field()# 章节地址chapterurl = scrapy.Field()# 章节名字chaptername = scrapy.Field()
复制代码

然后我们看一下入口地址 www.23us.so/

玄幻魔法:www.23us.so/list/1_1.ht…

武侠修真:www.23us.so/list/2_1.ht…

都市言情:www.23us.so/list/3_1.ht…

历史军事:www.23us.so/list//4_1.h…

网游竞技:www.23us.so/list/5_1.ht…

科幻小说:www.23us.so/list/6_1.ht…

恐怖灵异:www.23us.so/list/7_1.ht…

女生小说:www.23us.so/list/8_1.ht…

其他:www.23us.so/list/9_1.ht…

全本:www.23us.so/full.html

当然对于上面的地址,通过base_url + '_d'的方式请求

import re
import scrapy
from scrapy import Request
from bs4 import BeautifulSoup
from dingdian.items import DingdianItem, DcontentItem
from dingdian.mysqlpipelines.sql import Sqlclass MySpider(scrapy.Spider):name = "dingdian"allowed_domains = ['23us.so']base_url = 'https://www.23us.so/list/'def start_requests(self):for i in range(1, 10):url = self.base_url + str(i) + '_1' + '.html' #小说分类的urlyield Request(url, self.parse)# 全本yield Request('https://www.23us.so/full.html', callback=self.parse)
复制代码

对于上面的代码,创建一个类 Myspider,这个类继承自scrapy.Spider,定义name:dingdian (请注意,这name就是在run.py文件中的第三个参数!),此Name的名字在整个项目中有且只能有一个,名字不可重复!

定义了一个allowed_domains;这个不是必须的,但是在某些情况下需要用得到,比如使用爬取规则的时候就需要了,它的作用是只会跟进存在于allowed_domains中的URL,不存在的URL会被忽略。使用字符串拼接的方式实现了上面发现的小说分类的所有URL。

最后使用parse函数接受上面request获取到的response,返回的response中的url便是每个小说分类的链接,每个分类下有很多页的内容,我们需要拿到页码

找到此处页码的标签

 def parse(self, response):max_num = response.css('div.pagelink a.last::text').extract_first()for num in range(1, int(max_num) + 1):next_page = str(response.url)[:-7] + '_' + str(num) + '.html'if next_page is not  None:yield Request(next_page, callback=self.get_name)
复制代码

然后通过字符串拼接出每一页的链接next_page,当next_page存在的时候,便去请求,这里response.css是通过css选择器来查找标签的,查找标签的方式有很多,可以用css,xpath,或者BeautifulSoup。可以通过chrome或者Firefox快速获取到指定标签的css和xpath路径。在chrome中打开代码检查,点击这个图标

然后在网页上选择你要查看的内容,便会自动跳转到指定内容的html标签,然后在标签上右键便可复制css和xpath路径,这样取出的路径会比自己写的长,所以我还是选择自己写比较简洁。

上面两个函数就彻底的把整个网站的所有小说的页面URL的提取出来了,并将每个页面的response交给了get_name函数处理。

    def get_name(self, response):tds = BeautifulSoup(response.text, 'lxml').find_all('tr', bgcolor='#FFFFFF')for td in tds:novelname = td.find('a').get_text()novelurl = td.find('a')['href']yield Request(novelurl, callback=self.get_chapterurl, meta={'name': novelname, 'url': novelurl})
复制代码

获取小说name和url,通过reques的meta将额外参数传递给get_chapterurl函数

    def get_chapterurl(self, response):item = DingdianItem()item['name'] = str(response.meta['name']).replace('\xa0', '')item['novelurl'] = response.meta['url']category = response.css('table a::text').extract_first()author = response.css('table td::text').extract()[1]# 最新章节bash_url = response.css('p.btnlinks a.read::attr(href)').extract_first()name_id = str(bash_url).split('/')[-2]item['category'] = str(category).replace('/', '')item['author'] = str(author).replace('/', '')item['name_id'] = name_idyield itemyield Request(url=bash_url, callback=self.get_chapter, meta={'name_id': name_id})
复制代码

将需要的数据,复制给item[key] (注意这儿的Key就是前面在item文件中定义的那些字段)

注意!response.meta[key]:这个是提取从上一个函数传递下来的值。

return item 就是返回我们的字典了,然后Pipelines就可以开始对这些数据进行处理了。比如存储到MySQL中。

遍历每个小说的章节和之前的操作类似,都是查找标签,接下来我们说说通过Pipeline存储到MySQL的问题

新建两张表,一张存储 书名 + 作者 + 分类,另一张存储 章节名称 + 内容,我是用navicate for mysql管理的数据库

DROP TABLE IF EXISTS `dd_name`;
CREATE TABLE `dd_name` (`id` int(11) NOT NULL AUTO_INCREMENT,`xs_name` varchar(255) DEFAULT NULL,`xs_author` varchar(255) DEFAULT NULL,`category` varchar(255) DEFAULT NULL,`name_id` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4;
复制代码
DROP TABLE IF EXISTS `dd_chaptername`;
CREATE TABLE `dd_chaptername` (`id` int(11) NOT NULL AUTO_INCREMENT,`xs_chaptername` varchar(255) DEFAULT NULL,`xs_content` text,`id_name` int(11) DEFAULT NULL,`num_id` int(11) DEFAULT NULL,`url` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2726 DEFAULT CHARSET=gb18030;
SET FOREIGN_KEY_CHECKS=1;
复制代码

在settings.py文件中定义好MySQL的配置文件,账户密码端口和数据库都根据自己本地的配置填写,‘DingDianBooks’是我为这个项目建的数据库,默认的端口一般都是3306.

# mysql
MYSQL_HOSTS = '127.0.0.1'
MYSQL_USER = 'root'
MYSQL_PASSWORD = '11111'
MYSQL_PORT = '3306'
MYSQL_DB = 'DingDianBooks'
复制代码

Python连接MySQL数据库需要下载另外的包,我这里使用的是mysql-connector,通过pip安装管理。

下面是我们的sql.py文件:

import mysql.connector
from dingdian import settings# mysql
MYSQL_HOSTS = settings.MYSQL_HOSTS
MYSQL_USER = settings.MYSQL_USER
MYSQL_PASSWORD = settings.MYSQL_PASSWORD
MYSQL_PORT = settings.MYSQL_PORT
MYSQL_DB = settings.MYSQL_DBcnx = mysql.connector.connect(user=MYSQL_USER, password=MYSQL_PASSWORD, host=MYSQL_HOSTS, database=MYSQL_DB)
cur = cnx.cursor(buffered=True)class Sql:# 插入书名 + 作者 + 分类@classmethoddef insert_dd_name(cls , xs_name, xs_author, category, name_id):sql = 'INSERT INTO dd_name (`xs_name`, `xs_author`, `category`, `name_id`) VALUES (%(xs_name)s, %(xs_author)s, %(category)s, %(name_id)s)'value = {'xs_name' : xs_name,'xs_author': xs_author,'category': category,'name_id': name_id}cur.execute(sql, value)cnx.commit()# 去重@classmethoddef select_name(cls, name_id):sql = 'SELECT EXISTS(SELECT 1 FROM dd_name WHERE name_id=%(name_id)s)'value = {'name_id': name_id}cur.execute(sql, value)return cur.fetchall()[0]
复制代码

初始化了一个MySQL的操作游标,将函数中的四个变量写入数据库,select_name是一个去重函数,这个函数会查找name_id这个字段,如果存在则会返回 1 不存在则会返回0。

sqi.py这一部分完成,现在开始写pipeline:

from .sql import Sql
from dingdian.items import DingdianItem, DcontentItemclass DingDianPipeline(object):def process_item(self, item, spider):if isinstance(item, DingdianItem):name_id = item['name_id']ret = Sql.select_name(name_id)if ret[0] == 1:print('已经存在')passelse:xs_name = item['name']xs_author = item['author']category = item['category']Sql.insert_dd_name(xs_name, xs_author, category, name_id)
复制代码

建立了一个DingdianPipeline的类,别忘了一定要继承object,定义了一个process_item函数并有item和spider这两个参数,这两个参数是必须的,当item中存在DingdianItem,先执行去重,然后就从item中取出值然后存入数据库。 另一种表的存取方式是类似的,详细的可以去看代码。

到此,真个爬虫差不多完成了,只需要在PyCharm中运行run.py便可以执行爬虫。

项目地址GitHub

转载于:https://juejin.im/post/5ba342cf6fb9a05cdc498400

Scrapy爬取顶点小说相关推荐

  1. Scrapy爬取顶点小说网

    Scrapy爬取小说 爬取目标:顶点小说网 1.Scrapy的安装 pip install scrapy 2.Scrapy的介绍 创建项目 scrapy startproject xxx xxx项目名 ...

  2. Python的scrapy之爬取顶点小说网的所有小说

    闲来无事用Python的scrapy框架练练手,爬取顶点小说网的所有小说的详细信息. 看一下网页的构造: tr标签里面的 td 使我们所要爬取的信息 下面是我们要爬取的二级页面 小说的简介信息: 下面 ...

  3. Python网络爬虫(九):爬取顶点小说网站全部小说,并存入MongoDB

    前言:本篇博客将爬取顶点小说网站全部小说.涉及到的问题有:Scrapy架构.断点续传问题.Mongodb数据库相关操作. 背景: Python版本:Anaconda3 运行平台:Windows IDE ...

  4. scrapy-redis分布式爬虫全站爬取顶点小说网

    scrapy-redis是一个基于redis的scrapy组件,通过它可以快速实现简单分布式爬虫程序,该组件本质上提供了三大功能: scheduler - 调度器 dupefilter - URL去重 ...

  5. scrapy爬取起点小说网

    闲来无事,在学习过程中练习用scrapy爬取起点小说名 工具:python3.6 操作系统:linux 浏览器:谷歌浏览器 创建项目 在黑屏终端创建一个项目:scrapy startproject Q ...

  6. python3.6爬虫案例:爬取顶点小说(爱看小说同学的福利)

    一.写在前面 这次本来打算爬百思不得姐视频的,谁料赶上此网站调整,视频专栏下线了,网站中也没有视频可爬.所幸先来说说如何爬取顶点小说吧. 顶点小说(https://www.x23us.com)里面的内 ...

  7. python爬取顶点小说简单版

    python爬取顶点小说简单版 爬取网络资源首先要下载requests库 因为这里面也有数据提取和分析所以也要有etree库,re库 下载库的代码是:pip install 库名 如:pip inst ...

  8. Scrapy 爬取盗墓笔记小说

    Scrapy 爬取盗墓笔记小说 应用 Scrapy框架 爬取盗墓笔记小说数据,存入MongoDB 数据库. # settings 配置mongodb MONGODB_HOST = '127.0.0.1 ...

  9. 用Python爬取顶点小说网站中的《庆余年》思路参考——记一次不成功的抓取

    目的:用python爬虫抓取顶点小说网站中的<庆余年>小说内容个,并保存为txt格式文件. 环境:Win10系统,Anaconda3 + PyCharm, python3.6版本 思路:( ...

最新文章

  1. 架构师之前,请先进阶,不要只会 Spring
  2. SQL Server 2016:实时查询统计
  3. PXE安装CentOS
  4. [处理器、单片机]ARM
  5. MPlayer在ARM上的移植(S5PV210开发板)
  6. [python3 - TroubleShooting] requests爬取中文网站后直接print,以及保存csv乱码
  7. WCF学习- 体系结构
  8. aboboo 上一句 快捷键_锁定微信防别人偷看,苹果电脑上的微信有何不同?
  9. [零基础学JAVA]Java SE应用部分-34.Java常用API类库
  10. C++类占字节数讲解
  11. 腾讯云mysql升级失败怎么办_本地连接腾讯云Mysql失败问题
  12. zoj2587唯一最小割
  13. oracle 删除数据_2020最新最全数据库系统安全
  14. unrecognized selector sent to instance的一类解决办法
  15. 同花顺通达信公式指标改写成python实现代码,纯numpy,无循环!
  16. 2020 DEMO CHINA首次进入成都,解码智慧经济新时代
  17. 工作中提升效率的工具
  18. panda3d python教程_图解 Panda3D引擎开发入门
  19. 【Python零基础到入门】Python基础语法篇——基本数据类型【文末送书】
  20. python自动产品分类_商品分类(一堆多)

热门文章

  1. stm32初学之定时器TIM的基本定时功能以及介绍
  2. 【STM32F429开发板用户手册】第26章 STM32F429的定时器应用之TIM1-TIM14的中断实现
  3. linux驱动之系统移植-----uboot常用命令汇总
  4. springboot-banner
  5. 自己搞了个acid3测试
  6. 一段摩斯密码里的爱情故事
  7. sobel算子检测图像清晰度
  8. Linux服务器记录并查询历史操作记录
  9. 转:系统管理员最佳实践准则
  10. solomn数据集的分布情况简介