高手的存在,就是让服务10亿人的时候,你感觉只是为你一个人服务......

Scrapy网络爬虫

目录
  1. 1. Scrapy框架介绍
    1. 1.1. Scrapy框架图
    2. 1.2. 整体流程:
  2. 2. 制作Scrapy爬虫
    1. 2.1. 新建项目
    2. 2.2. 创建Spider
      1. 2.2.1. scrapy check
      2. 2.2.2. scrapy crawl运行spider
      3. 2.2.3. pipelines.py
    3. 2.3. scrapy shell
  3. 3. 实例:爬取博客文章信息
    1. 3.1. 创建spider项目
    2. 3.2. 创建spider爬虫
    3. 3.3. 编写爬取逻辑
      1. 3.3.1. 编写items.py
      2. 3.3.2. 编写spider.py
      3. 3.3.3. 编写pipeline.py
      4. 3.3.4. 修改settings.py
    4. 3.4. scrapy check&& scrapy crawl

网络爬虫简单来说就是模拟用户操作浏览器或者app,并获取、筛选信息的程序。

Alt text


Scrapy框架介绍

目前比较流行的python网络爬取框架-Scrapy,在数据挖掘、监测和自动化测试上也有一些应用。

Scrapy框架图

Scrapy 使用 Twisted异步网络库来处理网络通讯,包含了各种中间件接口,可以灵活的完成各种需求。

Alt text

Scrapy Engine(引擎):总负责人。负责其他模块的通信、数据传递等。

Scheduler(调度器):负责接收引擎发过来的request请求,放入队列中;当引擎需要时返回给引擎。

Downloader(下载器): 负责下载引擎发送的所有request请求,将获取的reponse返回给引擎,引擎交给spiders模块进行数据处理。

Spiders(爬虫):使用各种解析规则,分析提取Item数据,并将需要跟进的url提交给引擎,再次进入scheduler。

Item Pipeline(管道):负责处理spider中获取的item,进行后续详细分析、存储等处理。

Downloader Middlewares和Spider Middlewares: 可以自定义扩展的组件。

整体流程:

  1. 引擎询问Spiders有木有需要爬取的url。
  2. 引擎获取到需要爬取的url,交给Scheduler,放入下载队列中。
  3. 引擎从Scheduler队列中拿到下一个需要爬取的url,交给Downloader进行下载。(如果下载失败了URL会再次进入Scheduler队列中)
  4. 引擎将Downloader下载的Response交给Spiders进行处理。
  5. Spiders处理Response,把获取的item交给Item Pipeline;将需要继续跟进的url交给引擎放入Scheduler队列中。
  6. 循环1~5,直到Scheduler中不存在任何url。

制作Scrapy爬虫

首先安装Scrapy,这里使用的python2.7版本

pip install Scrapy

输入scrapy,验证是否安装成功。
Alt text

新建项目

执行 scrapy startproject project名字 即可。

Alt text

Alt text

scrapy.cfg : 项目的总体配置
items.py : 项目的目标文件
pipelines.py : 项目的管道文件
settings.py :项目的配置文件
spiders文件夹:爬虫代码存储目录


创建Spider

进入spiders文件夹,执行scrapy genspider [-t template] 命令即可

Alt text

默认使用basic模板,执行后生成baiduspider.py文件:
修改parse方法,打印返回的body

1
2
3
4
5
6
7
8
9
10
11
12
# -*- coding: utf-8 -*-
import scrapy


class MicspiderSpider(scrapy.Spider):
name = 'micspider' #保证唯一性
allowed_domains = ['www.made-in-china.com']
start_urls = ['http://www.made-in-china.com/']

def parse(self, response): # 负责解析返回的response,提取数据或者生成跟进的url对象
print response.body
# pass

scrapy check

修改完spider文件,check一下。

scrapy check micspider

check后面的爬虫名称为spider文件中定义的name名称。

Alt text

scrapy crawl运行spider

运行spider

scrapy crawl micspider

会打印出mic网站的body信息。

pipelines.py

当item在spider中被收集后,它会被传递到item pipeline中,这些item pipeline组件按照settings.py文件中定义的顺序处理item。

我们修改一下生成的pipelines.py,把item打印到文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html

import json

class SpiderprojectPipeline(object):

#可选实现,做一些初始化
def __init__(self):
self.f = open("mic.json","w")

#必须实现
#item参数为spider返回的item数据
#spider参数为获取item的spider对象
def process_item(self, item, spider):
content = json.dumps(dict(item))
self.f.write(content)
return item

#可选实现,放spider启动的时候,调用该方法
#def open_spider(self,spider):
pass

#可选实现,当spider关闭时,调用该方法
def close_spider(self,spider):
self.f.close()

items.py 和 micspider.py 文件做相应修改:

items.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class SpiderprojectItem(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()

#pass

micspider.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding: utf-8 -*-
import sys
sys.path.append("..")
import scrapy
from items import SpiderprojectItem

class MicspiderSpider(scrapy.Spider):
name = 'micspider'
allowed_domains = ['www.made-in-china.com']
start_urls = ['http://www.made-in-china.com/']

def parse(self, response):

node = response.body

item = SpiderprojectItem()
item['name'] = node

yield item

修改settings.py文件,把pipeline的设置放开:

1
2
3
ITEM_PIPELINES = {
'spiderproject.pipelines.SpiderprojectPipeline': 300,
}

这里可以设置多个pipeline,300表示权重。
权重为1~1000之间,越小表示权重越大。

ok , 配置完以上信息,执行scrapy crawl micspider,
执行后会生成一个mic.json文件,里面是mic网站的body。

tips:
spider.py文件中,最后return的数据给引擎,由引擎来判断由谁处理数据。
当return的数据为item类型时,引擎才交给pipeline处理。


scrapy shell

执行scrapy shell xxxx,启动一个交互终端,方便进行爬取的网页数据调试,比如测试xpath。

scrapy shell http://tonylit.me/

Alt text


以上就是scrapy爬虫主要的功能点。


实例:爬取博客文章信息

下面对我自己的博客进行文章标题、标签、链接、发布时间进行爬取。实现一个简单的scrapy爬虫。

url: http://tonylit.me/

Alt text


创建spider项目

项目的名字:myblogspider

scrapy startproject myblogspider


创建spider爬虫

爬虫的名字:tonylitspider

进入myblogspider文件夹中,执行:

scrapy genspider tonylitspider ‘tonylit.me’

在spiders文件夹中生成tonylitspider.py的爬虫文件


编写爬取逻辑

在编写之前,先把需要爬取信息的xpath弄清楚。

title-list: //a[@class=’article-title’]/text()
tag-list: //ul[@class=’article-tag-list’]/li/a/text()
link-list://a[@class=’article-title’]/@href
time-list ://time/@datetime

编写items.py

定义四个变量,存储文章的标题、标签、链接、发布时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html


import scrapy


class MyblogspiderItem(scrapy.Item):
# define the fields for your item here like:
# 文章标题

title = scrapy.Field()
# 文章标签

tag = scrapy.Field()
# 文章链接

link = scrapy.Field()
# 发布时间

time = scrapy.Field()

编写spider.py

编写上面生成的tonylitspider.py,实现信息的爬取。

找到下一页的xpath:

下一页://a[@class=’extend next’]/@href

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# -*- coding: utf-8 -*-
import scrapy
import sys
sys.path.append("..")
from items import MyblogspiderItem

class TonylitspiderSpider(scrapy.Spider):

#爬虫名称
name = 'tonylitspider'

#爬取域范围,允许爬虫在这个域名下进行爬取(可选)
allowed_domains = ['tonylit.me']

baseURL = "http://tonylit.me/"
#从此url开始爬取
start_urls = ['http://tonylit.me/']

def parse(self, response):

#获取文章标题
title_list = response.xpath("//a[@class='article-title']/text()").extract()

#获取文章标签
tag_list = response.xpath("//ul[@class='article-tag-list']/li/a/text()").extract()

#获取文章链接
link_list = response.xpath("//a[@class='article-title']/@href").extract()

#获取发布时间
time_list = response.xpath("//time/@datetime").extract()

#创建items对象-orm
items = MyblogspiderItem()

try:
#每页8篇文章
for temp in range(1,8):
#存储文章标题到item
items['title'] = title_list[temp].encode("utf-8")

#存储文章标签到item
items['tag'] = tag_list[temp].encode("utf-8")

#存储文章链接到item
items['link'] = str("http://tonylit.me") + link_list[temp].encode("utf-8")

#存储发布时间到item
items['time'] = time_list[temp].encode("utf-8")

yield items

except :
print "error"
else:
#进行翻页处理
nextPage = response.xpath("//a[@class='extend next']/@href").extract()[0].encode("utf-8")
if len(nextPage) != 0:
nextURL = 'http://tonylit.me/'+ str(nextPage)
print nextURL
#递归调用parse
yield scrapy.Request(nextURL,callback = self.parse)


if __name__ == "__main__" :
pass

编写pipeline.py

编写管道文件,把爬取的信息输出到文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
import json

class MyblogspiderPipeline(object):


#初始化,打开tonylit.json文件,用来写入items
def __init__(self):
self.f = open("tonylit.json","w")

def process_item(self, item, spider):

#把item转成字典,写入文件中
content = json.dumps(dict(item)) + ", \n"
self.f.write(content)

return item


#spider全部结束后,关闭文件
def close_spider(self,spider):
self.f.close()

修改settings.py

把ITEM_PIPELINES 配置放开,启用pipeline

1
2
3
ITEM_PIPELINES = {
'myblogspider.pipelines.MyblogspiderPipeline': 300,
}


scrapy check&& scrapy crawl

编写完成后,先进行check,再执行爬虫

scrapy check tonylitspider
scrapy crawl tonylitspider

执行后,生成tonylit.json,里面就是爬取的信息了。