学习自: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,使用原理及总结的更多相关文章

  1. python进阶01 面向对象、类、实例、属性封装、实例方法

    python进阶01 面向对象.类.实例.属性封装.实例方法 一.面向对象 1.什么是对象 #一切皆对象,可以简单地将“对象”理解为“某个东西” #“对象”之所以称之为对象,是因为它具有属于它自己的“ ...

  2. Python进阶开发之元类编程

    系列文章 √第一章 元类编程,已完成 ; 本文目录 类是如何产生的如何使用type创建类理解什么是元类使用元类的意义元类实战:ORM . 类是如何产生的 类是如何产生?这个问题肯定很傻.实则不然,很多 ...

  3. 孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习

     孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.close() 当一个file对象执行此方法时,将关闭当前 ...

  4. python scrapy 抓取脚本之家文章(scrapy 入门使用简介)

    老早之前就听说过python的scrapy.这是一个分布式爬虫的框架,可以让你轻松写出高性能的分布式异步爬虫.使用框架的最大好处当然就是不同重复造轮子了,因为有很多东西框架当中都有了,直接拿过来使用就 ...

  5. python基础——面向对象进阶下

    python基础--面向对象进阶下 1 __setitem__,__getitem,__delitem__ 把对象操作属性模拟成字典的格式 想对比__getattr__(), __setattr__( ...

  6. 【转】Python之函数进阶

    [转]Python之函数进阶 本节内容 上一篇中介绍了Python中函数的定义.函数的调用.函数的参数以及变量的作用域等内容,现在来说下函数的一些高级特性: 递归函数 嵌套函数与闭包 匿名函数 高阶函 ...

  7. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

     1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...

  8. python Scrapy安装和介绍

    python Scrapy安装和介绍 Windows7下安装1.执行easy_install Scrapy Centos6.5下安装 1.库文件安装yum install libxslt-devel ...

  9. python 面向对象终极进阶之开发流程

    好了,你现在会了面向对象的各种语法了,  但是你会发现很多同学都是学会了面向对象的语法,却依然写不出面向对象的程序,原因是什么呢?原因就是因为你还没掌握一门面向对象设计利器, 此刻有经验的人可能会想到 ...

随机推荐

  1. 【程序18】求s=a+aa+aaa+aaaa+aa...a的值

    求s=a+aa+aaa+aaaa+aa-a的值,其中a是一个数字.例如2+22+222+2222+22222(此时共有5个数相加),几个数相加由键盘控制. 知识点:在Python 3里,reduce( ...

  2. python网络爬虫-入门(一)

    前言 1.爬虫程序是Dt(Data Technology,数据技术)收集信息的基础,爬取到目标网站的资料后,就可以分析和建立应用了. 2.python是一个简单.有效的语言,爬虫所需要的获取.存储.整 ...

  3. maven 项目搭建,本地环境配置。

    一,下载地址 http://maven.apache.org/download.cgi 英文不好的,可以在浏览器下载个翻译的插件,就好了,我用的是谷歌. 二, 解压文件,安装在自己制定的目录,注意安装 ...

  4. plsql 带参数的游标

    -- 带参数的游标 -- cursor c(no emp.deptno%type) is select * from emp where deptno=no; 参数的起名 不要和表中的列名相同! -- ...

  5. ApacheCN 所有教程/文档集已备份到 Coding

    QuantLearning 数据科学 WIKI 安全 WIKI 团队 WIKI Sklearn 中文文档 PyTorch 中文文档 TutorialsPoint 中文系列教程 Java8 中文官方教程 ...

  6. Android中四大组件

    Activity  BroadCast Receiver 广播接收者 Service  服务 Content Provider 内容提供者   四大组件都需要在清单文件里面配置一下

  7. VC 获取已系统安装的字体

    转载请注明来源:https://www.cnblogs.com/hookjc/ BOOL CALLBACK EnumFonts(CONST LOGFONT* lplf, CONST TEXTMETRI ...

  8. Java与网页JSP文件编码的小总结

    感谢大佬: https://www.cnblogs.com/yangguoe/p/8467672.html(编码发展史) https://blog.csdn.net/seabiscuityj/arti ...

  9. iOS程序的启动过程

    UIApplicationMain main函数中执行了一个UIApplicationMain这个函数 int UIApplicationMain(int argc, char *argv[], NS ...

  10. 动态路由与RIP协议

    动态路由与RIP协议 目录 动态路由与RIP协议 一.动态路由(Dynamic Route) 1.动态路由概述 2.动态路由特点 3.动态路由协议 (1)动态路由协议概述 (2)度量值 (3)收敛 4 ...