一、Scrapy框架简介

1. 下载页面
2. 解析
3. 并发
4. 深度

二、安装

linux下安装
pip3 install scrapy windows下安装
a.pip3 install wheel
b.下载twisted和pywin32 http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
c.进入下载目录
执行pip3 install Twisted-18.7.0-cp36-cp36m-win_amd64.whl #cp36为适合python3.6
执行pip3 install pywin32-224-cp36-cp36m-win_amd64.whl
  d.pip3 install scrapy
e.下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/ #找到适合本机python版本的64位

三、Scrapy整体架构图

  3.1 Scrapy使用Twisted异步网络库来处理网络通讯

  3.2 各个主要文件说明

  spiders(蜘蛛)文件夹:如ip138.com

name    #不能省略,最好不要修改
starts_urls #起始url
allowed_domains #爬取允许域名列表,起始url不受影响。网页中的外链受此限制

四、基本使用

1. 指定初始url
2. 解析器响应内容
- 给调度器
- 给item:pipeline;用于做格式化;持久化 基本步骤:
a:scrapy startproject 项目名 #创建项目
b:进入项目目录
c:scrapy genspider baidu www.baidu.com #创建start_url
d:打开项目名\spiders\baidu.py进行编辑
e:scrapy crawl baidu #执行,加--nolog可以不显示日志,如果没有内容显示,可能此IP已经有防爬机制,可换个不知名ip试试

五、筛选器

  5.1  Selector介绍

  在scrapy中,可以使用Selector筛选器,代替BeautifulSoup

  在scrapy项目里的spiders文件里的baidu.py爬虫文件编辑,导入Selecotr模块

from scrapy.selector import Selector

  5.2 Selector(response=response).xpath()基本用法

//        #表示子子孙孙,即所有
.// #当前对象的子孙中
/ #儿子
/div #儿子中的div标签
//div[@id] #所有标签含有id的div标签
/div[@id='i1'] #儿子中的div且id ='i1'的标签
obj.extract() #列表中每一个对象转换成字符串 ==>返回的是列表
obj.extract_first() #列表中每一各对象转换成字符串==>返回的是列表中第一个元素
//div/text() #获取所有div标签里的文本==》返回的是列表,元素是对象
//a/@href #获取所有a标签里的url==》返回的是列表,元素是对象
//a[starts-with(@href,"link")] #获取所有a标签,并且href属性是以link开头的
//a[re:test(@href,"/sitehome/p/\d+")]/@href #正则,获取所有a标签属性href符合/sitehome/p/数字的
//div[@id='i1'][@href=''xx] #[][]且的意思,即所有含有id='i1'且href='xxx'的div标签
//a[contains(@href, "link")] #所有href字段包含link字符串的a标签

  5.3 简单示例

  需求:在www.ip138.com网站里,打印如下a标签的文本内容和url地址

  在爬虫文件(baidu.py)里的parse类方法里编辑 

# -*- coding: utf-8 -*-
import scrapy
from scrapy.selector import Selector class BaiduSpider(scrapy.Spider):
name = 'baidu'
allowed_domains = ['ip138.com']
start_urls = ['http://www.ip138.com/'] def parse(self, response):
#请求该页面下所有a标签==》列表,每个元素都是对象
#找到div标签里有class=mod-guide属性下的所有子孙a标签里文本内容
text_obj_list = Selector(response=response).xpath('//div[@class="module mod-guide"]//a/text()') # 找到div标签里有class=mod-guide属性下的所有子孙a标签里url
url_obj_list = Selector(response=response).xpath('//div[@class="module mod-guide"]//a/@href') #将列表中对象转化成列表中字符串
text_str_list = text_obj_list.extract()
url_str_list = url_obj_list.extract() for a_text,a_url in zip(text_str_list,url_str_list):
print(a_text,a_url)

代码

  如何运行代码?

在cmd窗口,进入项目目录,运行scrapy  crawl  baidu

  5.4 获取当前网页中的所有页码实例

  需求:获取博客园里的首页页码url

  

  在爬虫文件(ip138.py)里的parse类方法里编辑

# -*- coding: utf-8 -*-
import scrapy
from scrapy.selector import Selector class Ip138Spider(scrapy.Spider):
name = 'ip138'
allowed_domains = ['www.cnblogs.com']
start_urls = ['https://www.cnblogs.com/'] urls_set = set() def parse(self, response):
# text_obj_list = Selector(response=response).xpath('//div[@class="module mod-guide"]//a/text()')
# url_obj_list = Selector(response=response).xpath('//div[@class="module mod-guide"]//a/@href')
#
# text_str_list = text_obj_list.extract()
# url_str_list = url_obj_list.extract()
#
# for text,url in zip(text_str_list,url_str_list):
# print(text,url) #获取当前页里的所有页码的url对象列表
url_obj_list = Selector(response=response).xpath('//div[@class="pager"]/a/@href')
##或者2: starts-with(@属性,'值开头')
#url_obj_list = Selector(response=response).xpath('//a[starts-with(@href,"/sitehome/p/")]/@href')
##或者3:正则表达式固定用法re:test(@属性值,"正则表达式")
#url_obj_list = Selector(response=response).xpath('//a[re:test(@href,"/sitehome/p/\d+")]/@href') #将对象列表转换成字符串列表
url_str_list = url_obj_list.extract()
for url in url_str_list:
print(url) #1.通过集合去除重复url
#2.使用加密的MD5存储url,好处:加密和等长
url_md5 = self.my_md5(url)
if url_md5 not in self.urls_set:
self.urls_set.add(url_md5)
print(url_md5)
else:
print('%s已经存在'%url_md5) def my_md5(self,url):
import hashlib
obj = hashlib.md5()
obj.update(bytes(url,encoding='utf-8'))
return obj.hexdigest()

代码

  5.5 获得当前网页里的页码自动请求爬取实例

  需求:自动爬取博客园的所有页码(基于5.4案例的基础)

  

  在爬虫文件(ip138.py)里的parse类方法里编辑

# -*- coding: utf-8 -*-
import scrapy
from scrapy.selector import Selector
from scrapy.http import Request class Ip138Spider(scrapy.Spider):
name = 'ip138'
allowed_domains = ['www.cnblogs.com']
start_urls = ['https://www.cnblogs.com/'] urls_set = set() def parse(self, response): #获取当前页里的所有页码的url对象列表
url_obj_list = Selector(response=response).xpath('//div[@class="pager"]/a/@href')
##或者2: starts-with(@属性,'值开头')
#url_obj_list = Selector(response=response).xpath('//a[starts-with(@href,"/sitehome/p/")]/@href')
##或者3:正则表达式固定用法re:test(@属性值,"正则表达式")
#url_obj_list = Selector(response=response).xpath('//a[re:test(@href,"/sitehome/p/\d+")]/@href') #将对象列表转换成字符串列表
url_str_list = url_obj_list.extract()
for url in url_str_list: #1.通过集合去除重复url
if url not in self.urls_set:
#print(url)
self.urls_set.add(url)
#拼接完整的url地址
full_url = self.start_urls[0] + url
#将url页码传给调度器去请求,并将下载的结果交给parse方法,yield的作用是将请求放入调度器
yield Request(url=full_url,callback=self.parse) for url in self.urls_set:
print(url)

代码

  在setting.py中结尾新增一行DEPTH_LIMIT=1来指定递归的层次,默认是0,所有层次

  实例中关键点概括

@href    #取属性值
starts-with(@href,"xx") #属性href的值以xx开始
re:test(@href,"/sitehome/p/\d+") #正则re:test固定搭配
yield Request(url=full_url,callback=self.parse) #交给调度器

六、item,pipeline使用

  6.1 需求:将博客园的文章标题和url保存到一个文件a.txt文件里。

     各文件代码如下:

# -*- coding: utf-8 -*-
import scrapy
from scrapy.selector import Selector
from scrapy.http import Request
from .. import items class Ip138Spider(scrapy.Spider):
name = 'ip138'
allowed_domains = ['www.cnblogs.com']
start_urls = ['https://www.cnblogs.com/'] urls_set = set() def parse(self, response): #获取当前页面里的标题和url==>返回字符串
title_str_list = Selector(response=response).xpath('//a[@class="titlelnk"]/text()').extract()
href_str_list = Selector(response=response).xpath('//a[@class="titlelnk"]/@href').extract() for title_str,href_str in zip(title_str_list,href_str_list):
#print(title_str,' ',href_str) #此处的参数title,和href来自于items.py文件里类Cnblogs里的属性
item_obj = items.Cnblogs(title=title_str,href=href_str) #将item对象传递给pipelines
yield item_obj #获取当前页里的所有页码的url对象列表
page_obj_list = Selector(response=response).xpath('//div[@class="pager"]/a/@href')
##或者2: starts-with(@属性,'值开头')
#page_obj_list = Selector(response=response).xpath('//a[starts-with(@href,"/sitehome/p/")]/@href')
##或者3:正则表达式固定用法re:test(@属性值,"正则表达式")
#page_obj_list = Selector(response=response).xpath('//a[re:test(@href,"/sitehome/p/\d+")]/@href') #将对象列表转换成字符串列表
page_str_list = page_obj_list.extract()
for url in page_str_list: #1.通过集合去除重复url
if url not in self.urls_set:
self.urls_set.add(url)
print(url) #拼接完整的url地址
full_url = self.start_urls[0] + url
#将url页码传给调度器去请求,并将下载的结果交给parse方法,yield的作用是将请求放入调度器
yield Request(url=full_url,callback=self.parse)

ip138.py文件

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html import scrapy class Cnblogs(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field()
href = scrapy.Field()

items.py文件

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html class Day0310Pipeline(object):
def process_item(self, item, spider):
content = "%s %s\n"%(item['title'],item['href'])
f = open('a.json','a')
f.write(content)
f.close()
# return item

pipelines.py文件

ITEM_PIPELINES = {
'day0310.pipelines.Day0310Pipeline': 300,
}

setting.py文件

  6.2 实例中关键点概括

#items.py文件中
class Cnblogs(scrapy.Item):
title = scrapy.Field()
href = scrapy.Field() #ip138.py文件中
from .. import items
item_obj = items.Cnblogs(title=title_str,href=href_str) #此处的参数title,和href来自于items.py文件里类Cnblogs里的属性 yield item_obj #将item对象传递给pipelines #pipelines.py文件中,可对收集到的数据进行存储
class Day0310Pipeline(object):
def process_item(self, item, spider): #item为ip138.py文件里的对象化的数据,spider为来自哪只蜘蛛对象
content = "%s %s\n"%(item['title'],item['href'])
f = open('a.json','a')
f.write(content)
f.close() #setting.py文件中注册下pipelines的类
ITEM_PIPELINES = {
'day0310.pipelines.Day0310Pipeline': 300,
}
数字越高越优先

Scrapy爬虫框架学习的更多相关文章

  1. scrapy爬虫框架学习笔记(一)

    scrapy爬虫框架学习笔记(一) 1.安装scrapy pip install scrapy 2.新建工程: (1)打开命令行模式 (2)进入要新建工程的目录 (3)运行命令: scrapy sta ...

  2. Scrapy 爬虫框架学习笔记(未完,持续更新)

    Scrapy 爬虫框架 Scrapy 是一个用 Python 写的 Crawler Framework .它使用 Twisted 这个异步网络库来处理网络通信. Scrapy 框架的主要架构 根据它官 ...

  3. Python之Scrapy爬虫框架安装及简单使用

    题记:早已听闻python爬虫框架的大名.近些天学习了下其中的Scrapy爬虫框架,将自己理解的跟大家分享.有表述不当之处,望大神们斧正. 一.初窥Scrapy Scrapy是一个为了爬取网站数据,提 ...

  4. scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250

    scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250 前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大 ...

  5. Scrapy爬虫框架(实战篇)【Scrapy框架对接Splash抓取javaScript动态渲染页面】

    (1).前言 动态页面:HTML文档中的部分是由客户端运行JS脚本生成的,即服务器生成部分HTML文档内容,其余的再由客户端生成 静态页面:整个HTML文档是在服务器端生成的,即服务器生成好了,再发送 ...

  6. Scrapy爬虫框架中的两个流程

    下面对比了Scrapy爬虫框架中的两个流程—— ① Scrapy框架的基本运作流程:② Spider或其子类的几个方法的执行流程. 这两个流程是互相联系的,可对比学习. 1 ● Scrapy框架的基本 ...

  7. 安装scrapy 爬虫框架

    安装scrapy 爬虫框架 个人根据学习需要,在Windows搭建scrapy爬虫框架,搭建过程种遇到个别问题,共享出来作为记录. 1.安装python 2.7 1.1下载 下载地址 1.2配置环境变 ...

  8. scrapy爬虫框架教程(二)-- 爬取豆瓣电影

    前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大家讲解一个完整爬虫的流程. 工具和环境 语言:python 2 ...

  9. Python爬虫教程-31-创建 Scrapy 爬虫框架项目

    本篇是介绍在 Anaconda 环境下,创建 Scrapy 爬虫框架项目的步骤,且介绍比较详细 Python爬虫教程-31-创建 Scrapy 爬虫框架项目 首先说一下,本篇是在 Anaconda 环 ...

随机推荐

  1. 快速掌握mongoDB(二)——聚合管道和MapReduce

    上一节简单介绍了一下mongoDB的增删改查操作,这一节将介绍其聚合操作.我们在使用mysql.sqlserver时经常会用到一些聚合函数,如sum/avg/max/min/count等,mongoD ...

  2. 浅入深出Vue:代码整洁之封装

    深入浅出vue系列文章已经更新过半了,在入门篇中我们实践了一个小小的项目. <代码整洁之道>一书中提到过一句话: 神在细节中 这句话来自20世纪中期注明现代建筑大师 路德维希·密斯·范·德 ...

  3. C#中对EXCEL保存的SAVEAS方法说明

    这两天做的导出报表的项目中,因为出现了一些问题所以对于excel一些方法参数有了一些认识, 首先:开始生成的是.xls格式的excel文件,但是某个sheet发现我本来dataTable的数据有8万多 ...

  4. 利用openpyxl模块处理excel表格

    一.选取表格中的内容创建图表 1.openpyxl支持利用工作表中单元格的数据,创建条形图.折线图.散点图等.步骤如下: 1).从一个矩形区域选择的单元格,创建一个Reference对象. 2).通过 ...

  5. c++中利用宏定义简化for循环使用

    话不多说,上方法 #define _for(i,a,b) for( int i=(a); i<(b); ++i) #define _rep(i,a,b) for( int i=(a); i< ...

  6. 《C# 语言学习笔记》——定义属性

    属性定义的方式与字段类似,但包含的内容比较多. 属性拥有两个类似于函数的块,一个块用于获取属性的值,另一个块用于设置属性的值.这两个块也称访问器,分别用于get和set关键字定义,可以用于控制对属性的 ...

  7. C# backgroundwork的使用方法

    引言:在 WinForms 中,有时要执行耗时的操作,在该操作未完成之前操作用户界面,会导致用户界面停止响应.解决的方法就是新开一个线程,把耗时的操作放到线程中执行,这样就可以在用户界面上进行其它操作 ...

  8. vue教程(四)--其他实用用法补充

    一.vue生命周期简单介绍 var App={ template:'', data(){ }, beforeCreated:function(){ //不能操作数据,只是初始化了事件等.. }, cr ...

  9. JavaOOP 第二章继承

    一 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具 ...

  10. Java入门 面向对象第一天

    面向对象 人为抽象的一种编程模型,在理解面向对象的代码时要按照抽象的模型来理解,不能只从代码字面来理解复杂的问题,学会拆分成一个一个独立的小问题,通过解决每一个小问题,最后解决一个大问题 类 类是事物 ...