python爬虫框架教程_Python爬虫框架【Scrapy】

认识Scrapy

Scrapy,Python开发的一个快速、高层次的屏幕抓取和web抓取框架

用于抓取web站点并从页面中提取结构化的数据

Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试

Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改

它也提供了多种类型爬虫的基类

如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持

Scrapy 架构

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

Scrapy Engine(引擎): 分配任务给其他模块,负责其它模块之间的通信,数据传递等

Scheduler(调度器): 接受引擎发送的Request请求,整理入队,当需要时返回给引擎

Downloader(下载器): 从引擎处接收并下载调度器整理后返回的Requests请求,并将获取的Responses返回给引擎

Spider(爬虫): 提供初始网址,接收并处理从引擎处接收下载器返回的Responses

分析并提取Item需要的数据返回给管道,并将需要跟进的网址url提交给引擎

Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。

Downloader Middlewares(下载中间件): 你可以当作是一个可以自定义扩展下载功能的组件

Spider Middlewares(Spider中间件): 你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件

(比如进入Spider的Responses;和从Spider出去的Requests)

流程:

->Spider 提交初始爬取网址相关信息给Engine

->Engine根据Spider提交的数据发起Requests给Scheduler

->Scheduler将接收到的Requests进行整理入队,再返还给Engine

->Engine将整理后的Requests请求发送给Downloader

->Downloader将Requests请求提交给网站服务器并将服务器返回的Responses交给Engine

->Engine将Responses交给Spider进行处理

->Spider将从Responses中提取Item字段需要的信息和需要跟进的url

信息交给pipelines,url则提交给Engine,进行下一次爬取

->pipelines将完成对信息的分析,筛选和存储等工作。

在Scheduler整理的Requests请求队列全部执行并处理完毕后,程序结束。

简化流程:

由于在Engine主要用于个模块之间的信息传递,可以简化工作流程如下:

Spider发送初始url ---------------> Scheduler整理请求并入队(Engine发起请求)

Scheduler 发送整理后的请求 ----------------->Downloader向网址提交请求并获取responses

Downloader发送获取的responses ------------------>Spider分析并提取Item所需信息和需要跟进的url

Spider发送Item所需信息 ----------------->pipelines分析,筛选,存储信息

Spider发送需要跟进的url -----------------> Scheduler整理请求并入队(Engine发起请求)

利用Scrapy制作爬虫

安装Scrapy

pip install scarpy

实现步骤

1.新建项目 (scrapy startproject projectname)

2.确定目标 (编写items.py)(即编写需要获取的Item字段)

3.制作爬虫 (编写spiders/xxspider.py)(分析responses并提取数据)

4.存储内容 (编写pipelines.py)(分析筛选数据并储存)

1.新建项目

命令:scrapy startproject projectname

projectname为需要指定的项目名

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

进入项目并利用tree命令输出项目结构

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

各文件作用

scrapy.cfg: 项目的配置文件。

TestSpider/: 项目的Python模块,将会从这里引用代码。

TestSpider/items.py: 项目的目标文件。

TestSpider/pipelines.py: 项目的管道文件。

TestSpider/settings.py: 项目的设置文件。

TestSpider/spiders/: 存储爬虫代码目录。

2.确定爬取目标(编写items.py)

我们以爬取菜鸟教程为例,网址: http://www.runoob.com/

需要的数据为 教程名 图片url 简要描述 教程url

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

编辑items.py如下:

Item定义了一个结构化数据字段,类似于字典,用于保存爬取到的数据

import scrapy

class TestspiderItem(scrapy.Item):

# define the fields for your item here like:

# name = scrapy.Field()

name = scrapy.Field() # 教程名

img_url = scrapy.Field() # 图片地址

desc = scrapy.Field() # 描述

url = scrapy.Field() # 教程链接

3.制作爬虫 (编写spiders/xxspider.py)

在项目目录中输入命令

命令:scrapy genspider spidername 'start_url'

spidername 为需要指定的爬虫名称

start_url为初始爬取地址

此时会在spiders目录中创建spidername.py文件,并添加必须的代码

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

import scrapy

class RunoobSpider(scrapy.Spider):

name = 'runoob'

allowed_domains = ['www.runoob.com']

start_urls = ['http://www.runoob.com/']

def parse(self, response):

pass

当然,使用命令不是必需的,也可以选择自己创建和编写

但使用命令帮我们免去了写一些必须代码的麻烦

在此基础上,根据我们的需求编写爬虫代码

编写代码如下:

import scrapy

# 导入在items中写好的类

from TestSpider.items import TestspiderItem

# 编写爬虫

class RunoobSpider(scrapy.Spider):

name = 'runoob' # 文件名

allowed_domains = ['www.runoob.com'] # 允许访问的网址

start_urls = ['http://www.runoob.com/'] # 开始访问的网址

def parse(self, response):

course = TestspiderItem() # 实例化一个Item数据对象

# 获取class为"item-top item-1"的节点

courseInfos = response.xpath('//a[@class="item-top item-1"]')

# 遍历节点

for courseInfo in courseInfos:

# 根据需求提取指定数据并存入Item的对象中

course['url'] = courseInfo.xpath('@href')[0].extract()

course['name'] = courseInfo.xpath('.//h4/text()')[0].extract()

course['img_url'] = courseInfo.xpath('.//img/@src')[0].extract()

course['desc'] = courseInfo.xpath('.//strong/text()')[0].extract()

# 输出测试文件观察获取数据是否正确

#open('test.log','w').write('%s\n%s\n%s\n%s'%(type(course['url']),course['name'],type(course['img_url']),type(course['desc'])))

# 返回数据

yield course

查看test.log中的数据

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

4.存储内容 (编写pipelines.py)

(1)使用命令存储:

scrapy crawl spidername -o spidername.(json|jsonl|csv|xml)

以json / json lines / csv / xml格式存储在当前路径下

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

存储的csv文件,默认按照ASCII码编码顺序排列

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

(2)编写pipelines.py(需要设置setting)自定义存储

定义一个管道类,完成写入操作

>>>>>>>>

保存至文件,保存json格式数据,文件名为runoob.txt

class TestspiderPipeline(object):

# 以‘只写’方式打开runoob.txt文件

def __init__(self):

self.f = open('runoob.txt','w')

# pipeline中执行的程序

def process_item(self, item, spider):

# 测试语句,item返回的是获取到的Item数据类型(前面定义过的类型)

# open('runoob.log','w').write(str(type(item)))

# 存储为json格式,不使用ascii编码,缩进为4

import json

line = json.dumps(dict(item),ensure_ascii=False,indent=4)

self.f.write(line+'\n')

return item

# 关闭文件

def close_spider(self):

self.f.close()

>>>>>>>>

保存至mysql数据库

创建数据库runoob并指定utf8编码格式(create database runoob default charset=utf8;)

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

class MysqlPipeline(object):

def __init__(self):

# 构造时链接数据库

import pymysql

self.conn =pymysql.connect(

host='localhost',

user='root',

password ='redhat',

database ='runoob',

charset ='utf8',

autocommit = True

)

# 创建游标

self.cur = self.conn.cursor()

# 创建数据表

create_sqli = 'create table if not exists course(教程名称 varchar(50),链接 varchar(300),教程简介 varchar(200))'

self.cur.execute(create_sqli)

def process_item(self, item, spider):

# 插入数据

insert_sqli = 'insert into course values("%s","%s","%s") '%(item['name'],item['url'],item['desc'])

self.cur.execute(insert_sqli)

return item

def close_spider(self):

# 关闭游标和连接

self.cur.close()

self.conn.close()

>>>>>>>>

保存媒体图片

# 图片存储

class ImagePipeline(ImagesPipeline):

# 获取媒体请求

def get_media_requests(self, item, info):

# 测试语句

# open('mooc.log','w').write(item['img_url'])

# 返回图片

yield scrapy.Request(item['img_url'])

# results是返回的一个元组(True ,{'url':xxx,'path':xxx,'checksum':xxx})

# info返回的是一个对象scrapy.pipelines.media.MediaPipeline.SpiderInfo

def item_completed(self, results, item, info):

# 测试语句

# for i in results:

# open('ni.txt', 'w').write(str(i)+'\n'+str(info))

# 获取results中的path

image_path = [x['path'] for ok,x in results if ok]

# path为None,则不包含图片,否则返回item

if not image_path:

raise Exception('不包含图片')

else:

return item

保存图片还需要在settings.py中设置图片保存的路径

管道默认不执行,需要在settings.py中修改设置

后面的数字设定优先级,数字越小,优先级越高

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

执行爬虫并查看保存的数据

执行爬虫

在工程路径中输入命令

命令: scrapy crawl spidername

spidername为爬虫文件名

查看数据

文件

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

数据库

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

图片

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值