Python:Scrapy(三) 进阶:额外的一些类ItemLoader与CrawlSpider,使用原理及总结
学习自:Python Scrapy 爬虫框架实例(一) - Blue·Sky - 博客园
这一节是对前两节内容的补充,涉及内容为一些额外的类与方法,来对原代码进行改进
原代码:这里并没有用前两节的代码,而是用了另一个爬虫的代码,作用是爬取千图网的图片信息。该爬虫的基本信息:
项目名:AdilCrawler
爬虫名:thousandPic
网址:www.58pic.com
开始爬取的网址:https://www.58pic.com/c/
Item类:AdilcrawlerItem
xpath表达式:
Author:/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()
Name:/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()
# -*- coding: utf-8 -*-
import scrapy
# 这里使用 import 或是 下面from 的方式都行,关键要看 当前项目在pycharm的打开方式,是否是作为一个项目打开的,建议使用这一种方式。
import AdilCrawler.items as items class ThousandpicSpider(scrapy.Spider):
name = 'thousandPic'
allowed_domains = ['www.58pic.com']
start_urls = ['https://www.58pic.com/c/'] def parse(self, response): item = items.AdilcrawlerItem()
author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
item['author'] = author
item['theme'] = theme
return item
补充内容
1、日志打印,写在parse方法下:
def parse(self,response):
...
self.log(author)
...
2、ItemLoader类:代替extract()、xpath()方法
1)从scrapy.loader导入ItemLoader
from scrapy.loader import ItemLoader
2)优化,写在spider.py文件
用add_xpath方法,代替XPath提取语句:xpath(xxx).extract()
import scrapy
from AdilCrawler.items import AdilcrawlerItem
from scrapy.loader import ItemLoader class ThousandpicoptimizeSpider(scrapy.Spider):
name = 'thousandPicOptimize'
allowed_domains = ['www.58pic.com']
start_urls = ['http://www.58pic.com/c/'] def parse(self, response):
i = ItemLoader(item = AdilcrawlerItem(),response = response )
i.add_xpath('author','/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()')
i.add_xpath('theme','/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()')
return i.load_item()
相当于:
i = items.AdilcrawerItem()
author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
i['author'] = author
i['theme'] = theme
yield i
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
i = ItemLoader(item = AdilcrawlerItem(),response = response )
i.add_xpath('author','/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()')
i.add_xpath('theme','/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()')
yield i.load_item()
3)修改pipelines.py,目的是将爬取到的内容保存到文件中;
Spider中爬取到的内容都会以参数item的形式传入pipelines.py文件中的相关方法,比如process_item,(这一点很重要,且对所有类型的爬虫都适用)
import json class AdilcrawlerPipeline(object):
def __init__(self):
self.filename = open('thousandPic.json','w')
def process_item(self, item, spider):
# ensure_ascii=False 可以解决 json 文件中 乱码的问题。
text = json.dumps(dict(item), ensure_ascii=False) + ',\n' # 这里是一个字典一个字典存储的,后面加个 ',\n' 以便分隔和换行。
self.filename.write(text)
return item
def close_spider(self,spider):
self.filename.close()
至于json序列化保存的方法,可以参考序列化 pickle JSON - ShineLe - 博客园
4)修改settings.py
ITEM_PIPELINES = {
'AdilCrawler.pipelines.AdilcrawlerPipeline': 300,
}
# 加入后,相当于开启pipeline,此时在执行爬虫,会执行对应的pipelines下的类,并执行该类相关的方法,比如这里上面的保存数据功能。
5)执行;由于在pipelines.py中已经写了文件保存方法,故此处不用-o参数输出为文件
scrapy crawl thousandPicOptimize
3、CrawlSpider类:翻页抓取
1)使用crawl模板创建一个CrawlSpider PicSpi(CrawlSpider的生成,与普通Spider不同)
scrapy genspider -t crawl PicSpi www.58pic.com
2)items.py:与之前相同;
import scrapy
class PicsItem(scrapy.Item):
authod=scrapy.Field() #作者
theme=scrapy.Field() #主题
pipelines.py同2
3)Spider文件PicSpi.py
需要用到另外三个类:LinkExtractor、CrawlSpider、Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.spider import CrawlSpider,Rule
完整代码:
# 导入链接规则匹配类,用来提取符合规则的链接
from scrapy.linkextractors import LinkExtractor
# 导入CrawlSpider类和Rule (①)
from scrapy.spiders import CrawlSpider, Rule
import AdilCrawler.items as items class ThousandpicpagingSpider(CrawlSpider):
name = 'thousandPicPaging'
allowed_domains = ['www.58pic.com']
start_urls = ['https://www.58pic.com/c/'] # Response中的链接提取规则,返回符合规则的链接匹配对象的List
# 根据翻页链接地址 http://www.58pic.com/c/1-0-0-03.html 找到相应的正则表达式
# 不能使用restrict_xpath,否则正则将失效
#(②)
page_link = LinkExtractor(allow='https://www.58pic.com/c/\S-\S-\S-\S\S.html', allow_domains='www.58pic.com')
#(③)
rules = (
Rule(page_link, callback='parse_item', follow=True), # 此处的 ','不能省略
) # 方法parse_start_url是为了解决parse_item()不能抓取第一页数据的问题
# 原因是第一页的正则表达式形式与之后若干页不同
# 该方法是CrawlSpider类下的方法,这里重写一下即可
#(④)
def parse_start_url(self, response):
i = items.AdilcrawerItem()
author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
i['author'] = author
i['theme'] = theme
yield i
#(⑤)
def parse_item(self, response):
i = items.AdilcrawerItem()
author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
i['author'] = author
i['theme'] = theme
yield i
对这段代码的说明:
①:库的导入,这一部分的内容是在通过指令生成CrawlSpider的时候自动生成的
②:得到每一页的链接
page_link = LinkExtractor(allow='https://www.58pic.com/c/\S-\S-\S-\S\S.html', allow_domains='www.58pic.com')
LInkExtractor构建链接时,需要参数allow与allow_domains,参数allow是各页URL的完整正则表达式,allow_domains是限定访问的范围;这样page_link便保存了访问每一页的方法。
③:根据每页链接构建访问规则
rules = (
Rule(page_link, callback='parse_item', follow=True), # 此处的 ','不能省略
)
a、用Rule方法,参数有三项:page_link、callback、follow,作用分别是:
page_link:②中构建的链接,由于是正则表达式,所以是一系列的链接
callback:对这些链接进行处理的函数,需要在之后补充在同一个类中
follow:是否根据链接自动进行下去
b、最后,必须加,逗号,以表明这是一个Tuple元组
④:访问第一页(针对第一页URL不与正则表达式相匹配的情况):parse_start_url
⑤:访问其他页(代码相同,只是方法名不同):parse_item
i = items.AdilcrawerItem()
author = response.xpath('/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()').extract()
theme = response.xpath('/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()').extract()
i['author'] = author
i['theme'] = theme
yield i
代码内容与普通情况下的要素提取相同
4)运行;运行方法倒是相同
scrapy crawl thousandPicPaging
4、综合,将2、3结合起来,同时使用ItemLoader、CrawlSpider
import scrapy
from scrapy.loader import ItemLoader
from scrapy.spiders import CrawlSpider,Rule
import AdilCrawler.items as items class ThousandpicpagingopSpider(CrawlSpider):
name='thousandPicPagingOp'
allowed_domains = ['www.58pic.com']
start_urls = ['http://www.58pic.com/c/'] page_link=LinkExtractor(allow='http://www.58pic.com/c/\S-\S-\S-\S\S.html',allow_domains='www.58pic.com')
rules=(
Rule(page_link,callback='parse_item',follow=True),
) def parse_start_url(self,response):
i=ItemLoader(item=items.AdilcrawlerItem(),response=response)
i.add_xpath('author','/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()')
i.add_xpath('theme','/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()')
yield i.load_item() def parse_item(self, response):
i = ItemLoader(item = items.AdilcrawlerItem(),response = response )
i.add_xpath('author','/html/body/div[4]/div[3]/div/a/p[2]/span/span[2]/text()')
i.add_xpath('theme','/html/body/div[4]/div[3]/div/a/p[1]/span[1]/text()') yield i.load_item()
5、总结
用CrawlSpider和ItemLoader写一个可以自动翻页的爬虫的一般流程及文件配置。
1)创建项目与爬虫
scrapy startproject XXX
scrapy genspider -t crawl xxxS url
2)items.py
import scrapy class xxxItem(scrapy.Item):
attr1=scrapy.Field()
attr2=scrapy.Field()
...
attrn=scrapy.Field()
3)pipelines.py
import json class xxxPipeline(object):
def __init__(self):
self.filename = open('xxx.json','w') #保存文件 def process_item(self,item,spider):
# ensure_ascii=False 可以解决 json 文件中 乱码的问题。
text = json.dumps(dict(item), ensure_ascii=False)
self.filename.write(text)
return item
def close_spider(self,spider):
self.filename.close()
4)settings.py
BOT_NAME =
SPIDER_MODULES =
NEWSPIDER_MODULE =
ROBOTSTXT_OBEY = False
ITEM_PIPELINES = {
'XXX.pipelines.xxxPipeline': 300,
}
5)spider.py
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.loader import ItemLoader
from scrapy.spiders import CrawlSpider, Rule
import XXX.items as items class XXXSpider(CrawlSpider):
name = 'xxxS'
allowed_domains = ['url']
start_urls = ['url'] page_link = LinkExtractor(allow='url regex', allow_domains='url')
rules = (
Rule(page_link, callback='parse_item', follow=True),
) #处理首页
def parse_start_url(self, response):
i = ItemLoader(item = items.XXXItem(),response = response )
i.add_xpath('attr1','attr1 xpath')
i.add_xpath('attr2','attr2 xpath')
yield i.load_item() # 处理其他页
def parse_item(self, response):
i = ItemLoader(item = items.XXXItem(),response = response )
i.add_xpath('attr1','attr1 xpath')
i.add_xpath('attr2','attr2 xpath')
yield i.load_item()
6)运行爬虫
scrapy crawl xxxS
Python:Scrapy(三) 进阶:额外的一些类ItemLoader与CrawlSpider,使用原理及总结的更多相关文章
- python进阶01 面向对象、类、实例、属性封装、实例方法
python进阶01 面向对象.类.实例.属性封装.实例方法 一.面向对象 1.什么是对象 #一切皆对象,可以简单地将“对象”理解为“某个东西” #“对象”之所以称之为对象,是因为它具有属于它自己的“ ...
- Python进阶开发之元类编程
系列文章 √第一章 元类编程,已完成 ; 本文目录 类是如何产生的如何使用type创建类理解什么是元类使用元类的意义元类实战:ORM . 类是如何产生的 类是如何产生?这个问题肯定很傻.实则不然,很多 ...
- 孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习
孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.close() 当一个file对象执行此方法时,将关闭当前 ...
- python scrapy 抓取脚本之家文章(scrapy 入门使用简介)
老早之前就听说过python的scrapy.这是一个分布式爬虫的框架,可以让你轻松写出高性能的分布式异步爬虫.使用框架的最大好处当然就是不同重复造轮子了,因为有很多东西框架当中都有了,直接拿过来使用就 ...
- python基础——面向对象进阶下
python基础--面向对象进阶下 1 __setitem__,__getitem,__delitem__ 把对象操作属性模拟成字典的格式 想对比__getattr__(), __setattr__( ...
- 【转】Python之函数进阶
[转]Python之函数进阶 本节内容 上一篇中介绍了Python中函数的定义.函数的调用.函数的参数以及变量的作用域等内容,现在来说下函数的一些高级特性: 递归函数 嵌套函数与闭包 匿名函数 高阶函 ...
- python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解
1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...
- python Scrapy安装和介绍
python Scrapy安装和介绍 Windows7下安装1.执行easy_install Scrapy Centos6.5下安装 1.库文件安装yum install libxslt-devel ...
- python 面向对象终极进阶之开发流程
好了,你现在会了面向对象的各种语法了, 但是你会发现很多同学都是学会了面向对象的语法,却依然写不出面向对象的程序,原因是什么呢?原因就是因为你还没掌握一门面向对象设计利器, 此刻有经验的人可能会想到 ...
随机推荐
- linux下查看 SELinux状态及关闭SELinux
SELinux全称为安全增强式 Security-Enhanced Linux(SELinux),是一个在内核中实践的强制存取控制(MAC)安全性机制.SELinux 首先在 CentOS 4 出现, ...
- 优化.NET 应用程序 CPU 和内存的11 个实践
https://michaelscodingspot.com/cpu-bound-memory-bound/ 优化.NET 应用程序 CPU 和内存的11 个实践 凡事都有其限度,对吧?汽车只能开这么 ...
- TF-IDF计算相似度为什么要对稀疏向量建立索引?
TF-IDF的向量表示的稀疏问题 之前在看tf-idf代码时候思考了一个问题,不知道对于初学的大部分同学有没有这样一个疑惑,用tf-idf值构成的向量,维度可能跟词表的大小有关,那么对于一句话来说,这 ...
- 微服务架构 | 10.1 使用 Sleuth 追踪服务调用链
目录 前言 1. Sleuth 基础知识 1.1 Sleuth 原理 2. 在服务中使用 Sleuth 追踪 2.1 引入 pom.xml 依赖文件 2.2 查看日志信息 最后 前言 参考资料: &l ...
- 带你读AI论文:NDSS2020 UNICORN: Runtime Provenance-Based Detector
摘要:这篇文章将详细介绍NDSS2020的<UNICORN: Runtime Provenance-Based Detector for Advanced Persistent Threats& ...
- AtCoder ABC 215 简要题解
A - B 模拟 C 可以直接爆搜,也可以写逐位确定的多项式复杂度算法,使用多重组合式求随意乱排的方案数. D 首先对 \(A\) 所有数暴力分解质因数,然后把遇到过的质因数打上标记. 接下来再对 \ ...
- NOIP2018 Day2T2 填数游戏
下面先给出大家都用的打表大法: 首先我们可以发现 \(n \le 3\) 的情况有 \(65pts\),而 \(n\) 这么小,打一下表何乐而不为呢?于是我写了一个爆枚每个位置再 \(check\) ...
- php include,require,include_once,require_once 的区别
include(),require(),include_once(),require_once()作用都是包含并运行指定文件,但是使用场景又有很大区别. 1.include()和require()的区 ...
- 使用Java开发桌面即时通讯程序遇到的问题
项目:https://www.lking.top/?p=87 1. JPanel面板绘制背景图片问题. 参考大佬:https://www.jb51.net/article/101516.htm 本项目 ...
- Python属性描述符
实现了__get__.set.__delete__中任意一个方法的类,称之为属性描述符. 属性描述符可以控制属性操作时的一些行为. 只要具有__get__方法的类就是描述符类. 如果一个类中具有__g ...