基于小浣熊漫画cms的python爬虫项目实战(一)
创建 Scrapy 爬虫框架项目
- 本篇是在 Anaconda 环境下,如果没有安装 Anaconda 请到官网下载安装
- 下载地址:Anaconda | Individual EditionAnaconda | Individual EditionAnaconda's open-source Individual Edition is the easiest way to perform Python/R data science and machine learning on a single machine.https://www.anaconda.com/download/Anaconda | Individual Edition
一、 Scrapy 爬虫框架项目的创建
1.打开【cmd】
2.进入你要使用的 Anaconda 环境
1.环境名可以在【Pycharm】的【Settings】下【Project:】下找到
2.使用命令:activate 环境名,例如:activate learn
3.进入想要存放 scrapy 项目的目录下
4.新建项目:scrapy startproject xxx项目名,例如:scrapy startproject dem
5.在文件资源管理器打开该目录,就会发现生成了好几个文件
6.使用 Pycharm 打开项目所在目录就可以了。这里我们就把项目创建好了,分析一下自动生成的文件的作用
1.2 Scrapy 爬虫框架项目的开发
- 1.使用 Pycharm 打开项目,截图:
- 2.项目的开发的大致流程:
- 1.明确需要爬取的目标/产品:编写 item.py
- 2.在 spider 目录下载创建 python 文件制作爬虫:
- 地址 spider/xxspider.py 负责分解,提取下载的数据
- 3.存储内容:pipelines.py
- Pipeline.py 文件
- 对应 pipelines 文件
- 爬虫提取出数据存入 item 后,item 中保存的数据需要进一步处理,比如清洗,去虫,存储等
- Pipeline 需要处理 process_item 函数
- process_item
- spider 提取出来的 item 作为参数传入,同时传入的还有 spider
- 此方法必须实现
- 必须返回一个 Item 对象,被丢弃的 item 不会被之后的 pipeline
- _ init _:构造函数
- 进行一些必要的参数初始化
- open_spider(spider):
- spider 对象对开启的时候调用
- close_spider(spider):
- 当 spider 对象被关闭的时候调用
- Spider 目录
- 对应的是文件夹 spider 下的文件
- _ init _:初始化爬虫名称,start _urls 列表
- start_requests:生成 Requests 对象交给 Scrapy 下载并返回 response
- parse:根据返回的 response 解析出相应的 item,item 自动进入 pipeline:如果需要,解析 url,url自动交给 requests 模块,一直循环下去
- start_requests:此方法尽能被调用一次,读取 start _urls 内容并启动循环过程
- name:设置爬虫名称
- start_urls:设置开始第一批爬取的 url
- allow_domains:spider 允许去爬的域名列表
- start_request(self):只被调用一次
- parse:检测编码
- log:日志记录
二 、爬取前的分析
2.1 在正式爬取资源前,我们可以利用scrapy shell来分析我们想爬取的漫画网页主页,整理下思路。在cmd中运行如下指令:
scrapy shell http://www.sixmh7.com/23370/
我们可以看到,输入命令后,就会有一些日志一样的东西显示出来,蓝色区域则显示出可以使用的scrapy命令,接下来我们需要用到“response”来进行爬取前的分析,你可以接着输入response.body这条命令,看看会输出什么
2.2.查看章节链接和章节名:我们利用浏览器打开开发者工具,查看一下漫画主页的链接,如图:
我们可以发现,章节链接都在<li>
里面,这里我们利用scrapy shell来提取一下:
2.2.1.提取章节名
response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/p/text()').extract()
2.2.2.提取章节链接
response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/@href').extract()
这里我们发现,这里并不是全部章节的内容,需要点击查看更多章节动态获取,接下来我们分析动态获取的接口(有一些漫画站不需要动态获取,只是把静态的内容隐藏了)
接下来获取全部的链接和章节名,就不截图了,下面直接上代码
# 章节链接地址
urls = response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/@href').extract()
# 获取所有的章节名
dir_names = response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/p/text()').extract()
data = {"id": 23370,"id2": 1
}
response = requests.post("http://www.sixmh7.com/bookchapter/", data=data)
for index in range(len(response.json())):link_url = "/23370/" + response.json()[index]['chapterid'] + ".html"urls.append(link_url)dir_name = response.json()[index]['chaptername']dir_names.append(dir_name)
2.3.分析图片链接来源
首先我们要理清楚一个思路:章节链接(link_urls)和图片链接(img_urls)是两种链接,你点进第一章后,利用开发者工具就能发现这一点。相当于说:每页漫画都有两个链接:页面链接和图片来源链接,2.2步中我们利用response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/@href').extract()获取到的是页面链接,而我们要做的就是首先跳转到这个页面,然后找到图片链接,最后将保存的图片链接下载。
2.3.1 接下来我们分析章节里的图片链接,如下图
2.3.2 获取本页的图片链接
这里,我们很容易就和上面一样想到,利response.xpath('//li[@id="page_01"]/img/@src').extract()
来获取图片链接,但是当你真正这么做了,就会发现输出为空。原因就在于这一段html是利用简单的js动态加载进去的,你可以利用response.body来查看html不经过css和js修饰的源码。就会发现并没有打印出图片的信息,只有一堆js
由于这里的动态加载方法较为简单,如下图,可以直接利用开发者工具查看到js代码,因此我们直接获取js,然后进行分析即可(后续复杂的动态请求晚点学)
但是在这里我们发现,这段js代码被加密了,所以我们需要对这段eval代码进行解密
从scrapy shell进去章节页面,输入如下命令获取js
response.xpath('//script/text()').extract()[2].strip()
eval_js = response.xpath('//script/text()').extract()[2].strip()js = """function decode(code) {if(code.indexOf("eval(function")>-1){code = code.replace(/^eval/, '');code = eval(code);return code;}}"""com = execjs.compile(js)images = com.call('decode', eval_js)[13:].replace(']', '').split(",")
2.4这里我把前面需要的内容整理下,方便直接看:
# 章节链接地址
urls = response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/@href').extract()
# 获取所有的章节名
dir_names = response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/p/text()').extract()
data = {"id": 23370,"id2": 1
}
response = requests.post("http://www.sixmh7.com/bookchapter/", data=data)
for index in range(len(response.json())):link_url = "/23370/" + response.json()[index]['chapterid'] + ".html"urls.append(link_url)dir_name = response.json()[index]['chaptername']dir_names.append(dir_name))#进入第一章分析
scrapy shell http://www.sixmh7.com/23370/1297116.html
#获取IMG SRC(注意输出的是js,还需要后续处理)
response.xpath('//script/text()').extract()[2].strip()
三、正式编写
1)items.py
class Sixmh7Item(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()# 漫画名book_name = scrapy.Field()# 漫画别名nick_name = scrapy.Field()# 分类tags = scrapy.Field()# 作者名字author = scrapy.Field()# 状态,1代表完结,0代表连载中end = scrapy.Field()# 封面图远程地址cover_url = scrapy.Field()# 章节名chapter_name = scrapy.Field()# 地区idarea_id = scrapy.Field()# 由图片标签组成的字符串images = scrapy.Field()# 章节序chapter_order = scrapy.Field()# 漫画简介summary = scrapy.Field()# 后台配置的api_keyapi_key = scrapy.Field()# 用来区别采集源,自己写src = scrapy.Field()# 用来唯一定义每个漫画,可以是该漫画的url,也可以是该漫画在被采集站的idsrc_url = scrapy.Field()# 用来唯一定义每个章节,与src_url同理c_src_url = scrapy.Field()# 章节链接link_url = scrapy.Field()
2)setting.py
BOT_NAME = 'sixmh7'SPIDER_MODULES = ['sixmh7.spiders']
NEWSPIDER_MODULE = 'sixmh7.spiders'
USER_AGENT = 'Mozilla/5.0'
ROBOTSTXT_OBEY = False
ITEM_PIPELINES = {'sixmh7.pipelines.Sixmh7Pipeline': 1,
}
3)sixmh.py(正式版)
class SixmhSpider(scrapy.Spider):name = 'sixmh'def __init__(self):# 章节链接server域名self.server_link = 'http://www.sixmh7.com'self.allowed_domains = ['www.sixmh7.com']self.start_urls = ['http://www.sixmh7.com/23370/']# 可以查看scrapy文档def start_requests(self):yield scrapy.Request(url=self.start_urls[0], callback=self.parse1)# 解析response,获取每个大章节图片链接地址def parse1(self, response):items = []# 漫画名book_name = response.xpath('//div[@class="cy_title"]/h1/text()').extract()[0]# 漫画别名nick_name = response.xpath('//div[@class="cy_title"]/h1/text()').extract()[0]# 分类tags = response.xpath('//div[@class="cy_xinxi"]/span/text()').extract()[3].replace("标签:", "")# 作者名字author = response.xpath('//div[@class="cy_xinxi"]/span/text()').extract()[0].replace("作者:", "")# 状态,1代表完结,0代表连载中status = response.xpath('//div[@class="cy_xinxi"]/span/font/text()').extract()[0]if '连载中' == status:end = 0else:end = 1# 封面图远程地址cover_url = response.xpath('//div[@class="cy_info_cover"]/img/@src').extract()[0]# 漫画简介summary = response.xpath('//div[@class="cy_xinxi cy_desc"]/p/text()').extract()[0]# 章节链接地址urls = response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/@href').extract()# 获取所有的章节名dir_names = response.xpath('//ul[@id="mh-chapter-list-ol-0"]/li/a/p/text()').extract()data = {"id": 23370,"id2": 1}response = requests.post("http://www.sixmh7.com/bookchapter/", data=data)for index in range(len(response.json())):link_url = "/23370/" + response.json()[index]['chapterid'] + ".html"urls.append(link_url)dir_name = response.json()[index]['chaptername']dir_names.append(dir_name)# 保存章节链接和章节名for index in range(len(urls)):item = Sixmh7Item()item['api_key'] = 'abc123456'item['link_url'] = self.server_link + urls[index]item['chapter_name'] = dir_names[index]item['chapter_order'] = re.sub('\D', '', dir_names[index])item['book_name'] = book_nameitem['nick_name'] = nick_nameitem['tags'] = tagsitem['author'] = authoritem['end'] = enditem['cover_url'] = cover_urlitem['summary'] = summaryitem['src'] = self.server_linkitem['src_url'] = self.start_urls[0]item['c_src_url'] = self.server_link + urls[index]item['area_id'] = 1items.append(item)# 根据每个章节的连接,发送request请求,并传递item参数for item in items:yield scrapy.Request(url=item['link_url'], meta={'item': item}, callback=self.parse2)# 解析一个章节的第一页的页码数和图片链接def parse2(self, response):# 接收传递的itemitem = response.meta['item']# 下面一句不能少,是用来更新要解析的章节链接item['link_url'] = response.urlhxs = Selector(response)# 获取章节第一页图片的链接eval_js = hxs.xpath('//script/text()').extract()[2].strip()js = """function decode(code) {if(code.indexOf("eval(function")>-1){code = code.replace(/^eval/, '');code = eval(code);return code;}}"""com = execjs.compile(js)images = com.call('decode', eval_js)[13:].replace(']', '').split(",")tags = []for i in images:tags.append(eval(i))# 将获取的章节的第一页的图片链接保存到img_url中item['images'] = ','.join(tags)# 返回item,交给item pipeline下载图片yield item
这一段代码比较多,但是我相信只要你一步步敲过来,那么肯定很容易理解代码,而且我在学习原博客的过程中,也是遇到了许多坑,修改了很多地方,如果你直接复制我的代码却没法运行,你可以这么做:将报错以后的地方全部注释,然后print输出报错的东西(比如item报错你就print(item)一下),然后对照报错信息进行修改。
4)pipelines.py
import requestsclass Sixmh7Pipeline:def process_item(self, item, spider):url = 'http://www.xswang.online/api.php/postbot/save'print(item)res = requests.post(url=url, data=item)
5)运行
scrapy crawl sixmh
四、总结和后续
总的来说,学了这个教程后就有思路能爬取某个网站的所有漫画之类的了,但我依旧存在以下几个问题:
复杂的动态加载如何实现爬取
遇到需要登录,甚至需要vip的内容如何爬取
这些就留着接下来一段时间学习了
下一章将会进行6漫画网站的全站漫画爬取
小浣熊CMS爬虫实战(一)http://www.yzpblog.cn/index.php/2021/10/29/%e5%9f%ba%e4%ba%8e%e5%b0%8f%e6%b5%a3%e7%86%8a%e6%bc%ab%e7%94%bbcms%e7%9a%84python%e7%88%ac%e8%99%ab%e9%a1%b9%e7%9b%ae%e5%ae%9e%e6%88%98%ef%bc%88%e4%b8%80%ef%bc%89/
基于小浣熊漫画cms的python爬虫项目实战(一)相关推荐
- python爬虫项目-33个Python爬虫项目实战(推荐)
今天为大家整理了32个Python爬虫项目. 整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快~O(∩_∩)O WechatSogou [1] ...
- python爬虫知网实例-33个Python爬虫项目实战(推荐)
今天为大家整理了32个Python爬虫项目. 整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快~O(∩_∩)O WechatSogou [1] ...
- python爬虫项目实战教学视频_('[Python爬虫]---Python爬虫进阶项目实战视频',)
爬虫]---Python 爬虫进阶项目实战 1- Python3+Pip环境配置 2- MongoDB环境配置 3- Redis环境配置 4- 4-MySQL的安装 5- 5-Python多版本共存配 ...
- python爬虫新手项目-33个Python爬虫项目实战(推荐)
今天为大家整理了32个Python爬虫项目. 整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快~O(∩_∩)O WechatSogou [1] ...
- python爬虫教程推荐-33个Python爬虫项目实战(推荐)
今天为大家整理了32个Python爬虫项目. 整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快~O(∩_∩)O WechatSogou [1] ...
- python爬虫-33个Python爬虫项目实战(推荐)
今天为大家整理了32个Python爬虫项目. 整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快~O(∩_∩)O WechatSogou [1] ...
- post获取重定向的链接 python_欧美音乐网站Python爬虫项目实战
爬虫项目实战 0x01 目标分析 最近发现一个比较好的欧美音乐下载网站,可以下载大部分高质量欧美音乐.该爬虫项目要实现自动化批量获取用户想要下载的音乐.本文从网站分析.爬虫设计.代码实现三个方面出发, ...
- c++builder 运行网站的api_欧美音乐网站Python爬虫项目实战
爬虫项目实战 0x01 目标分析 最近发现一个比较好的欧美音乐下载网站,可以下载大部分高质量欧美音乐.该爬虫项目要实现自动化批量获取用户想要下载的音乐.本文从网站分析.爬虫设计.代码实现三个方面出发, ...
- 32个Python爬虫项目实战
转自:https://www.jb51.net/article/164829.htm 整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心.所有链接指向GitHub,祝大家玩的愉快~O(∩ ...
最新文章
- Python开发基础总结之套接字+字符串+正则表达式
- html分为哪两种,css伪类分为哪几种
- centos php fpm 内存,CentOS下yum安装PHP-配置php-fpm服务
- PHP-什么是PHP?为什么用PHP?有谁在用PHP?
- 翻译qmake文档(二) Getting Started
- ural 1066 uva 1555
- 三维计算机视觉(二)--点云滤波
- 「转载」蘑菇街消息系统上云实践
- osl倒数第三层_原子最外层、次外层及倒数第三层最多容纳电子数的解释
- 用无线局域网设置服务器,无线局域网怎样配置
- 微信公众号接入自己的客服系统,自定义客服系统
- Linux7中安装DNS服务,CentOS7/RHEL7搭建DNS服务器
- unity3d画出漂亮的玫瑰图案函数。
- MyBatis 报错 Could not initialize class
- php批量替换文件内容,写了个遍历目录、批量替换文件内容的类
- [Yocto RM]11 - Features
- Alibaba fastjson 序列化与反序列化
- labview调用python 开发视觉_龙哥教你学视觉—tensorflow目标检测LabVIEW深度学习教程...
- PAT乙级—1041 考试座位号 (15分)
- canvas封闭图形填充与
热门文章
- html 天气预报开发,html javascript 天气预报 (内附源代码)
- 经典windows sdk 程序设计网站
- 视频转换为swf格式
- java中dynamic_介绍@dynamic的用法
- 教你在Linux上使用ansible写“剧本”,定义一个“剧本”模板后,让控制集群自动执行我们剧本中所写的“剧情”,几个自动化运维的简单实例
- 都马上2020年了,还学什么PMP?
- linux 升内核 bbr,Linux 升级内核开启 TCP BBR 实现高效单边加速
- 通用CR安装教程|CORONA渲染器怎么一步一步安装到测试与成品大图出效果图渲染参数的设置?
- 树莓派(Linux)音频输出接口(HDMI和3.5mm耳机接口)相互切换方法
- 华为开源预训练语言模型「哪吒、TinyBERT」可直接下载使用