在上篇教程中,已经尝试安装好Scrapy,并且解决好了环境问题,这篇文章将创建一个Scrapy项目
包含的步骤主要为:
1、创建一个Scrapy项目
2、定义提取的字段信息Item
3、编写爬取网站的 spider 并提取 Item
4、编写 Item Pipeline 来存储提取到的Item(即数据)
开始爬取之前,必须创建一个新的Scrapy项目。 进入希望存储代码的目录中,运行下列命令:
scrapy startproject Alice
该命令将创建一个project项目,名称为Alice,并包含下列内容的 Alice 目录,:
Alice/
scrapy.cfg
Alice/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...
这些文件分别是:
- scrapy.cfg: 项目的配置文件
- Alice: 该项目的python模块。之后您将在此加入代码。
- Alice/items.py: 项目中的item文件.
- Alice/pipelines.py: 项目中的pipelines文件.
- Alice/settings.py: 项目的设置文件.
- Alice/spiders/: 放置spider代码的目录.
Item 是保存爬取到的数据的容器,并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。
通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field 的类属性来定义一个Item。
首先根据需要从csdn.blog获取到的数据对item进行建模。 我们需要从csdn中获取名字,url,以及网站的描述。 对此,在item中定义相应的字段。编辑 Alice 目录中的 items.py 文件:
import scrapy
class AliceItem(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()
# 标题
title = scrapy.Field()
# 详情连接
link = scrapy.Field()
# 阅读
read = scrapy.Field()
# 点赞
love = scrapy.Field()
# 分类
blogtype = scrapy.Field()
pass
Spider是用户编写用于从单个网站(或者一些网站)爬取数据的类。包含如下内容:
- 一个用于下载的初始URL
- 如何跟进网页中的链接
- 如何分析页面中的内容
- 提取生成 item 的方法。
为了创建一个Spider,必须继承 scrapy.Spider 类, 且定义以下三个属性:
- name: 用于区别Spider。 该名字必须是唯一的,为不同的Spider设定相同的名字是不允许的。
- start_urls: 包含Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
- parse() :是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。
创建一个spider文件,进入Alice目录,使用命令创建一个基础爬虫类:
# alicepostion为爬虫名,为爬虫作用范围
scrapy genspider alicepostion "blog.csdn.net/alice_tl"
以下为Spider代码,保存在 Alice/spiders 目录下的 aliceposition.py 文件中:
# -*- coding: utf-8 -*-
import scrapy
from Alice.items import AliceItem
class alicepostionSpider(scrapy.Spider):
#功能:爬取alice
name = 'alicepostion'
#爬虫名字
allowed_domains = ['blog.csdn.net/alice_tl']
#爬虫作用范围
start_urls = ['https://blog.csdn.net/alice_tl/']
#爬虫起始url
offset = 0
def parse(self, response):
for each in response.xpath("//tr[@class='even'] | //tr[@class='odd']"):
# 初始化模型对象
item = AliceItem()
# 标题
item['title'] = each.xpath("./td[1]/a/@href").extract()[0]
# 连接
item['link'] = each.xpath("./td[2]/text()").extract()[0]
# 阅读
item['read'] = each.xpath("./td[3]/text()").extract()[0]
# 点赞
item['love'] = each.xpath("./td[4]/text()").extract()[0]
# 分类
item['blogtype'] = each.xpath("./td[5]/text()").extract()[0]
yield item
if self.offset < 1680:
self.offset += 10
# 每次处理完一页的数据之后,重新发送下一页页面请求
# self.offset自增10,同时拼接为新的url,并调用回调函数self.parse处理Response
yield scrapy.Request(self.url + str(self.offset), callback = self.parse)
def parse(self, response):
filename = '/Users/alice/Documents/Develop/PythonCode/alicescrapy.xlsx'
#文件路径和文件名
with open(filename,'wb' ) as f:
#打开一个文件
f.write(response.body)
#将返回内容写进去
print(f.read())
pass
进入项目的根目录,执行下列命令启动spider:
scrapy crawl alicepostion
查看包含 [alicepostion] 的输出,可以看到输出的log中包含定义在 start_urls 的初始URL,并且与spider中是一一对应的。在log中可以看到其没有指向其他页面( (referer:None) )。
2019-04-20 11:13:58 [scrapy.core.engine] INFO: Spider opened
2019-04-20 11:13:58 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2019-04-20 11:13:58 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)
2019-04-20 11:13:58 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)
2019-04-20 11:13:58 [scrapy.core.scraper] ERROR: Spider error processing (referer: None)
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/twisted/internet/defer.py", line 654, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/Users/alice/Alice/Alice/spiders/alicepostion.py", line 47, in parse
with open(filename, '/Users/alice/Documents/Develop/PythonCode/alicescrapy.csv') as f:
ValueError: invalid mode: '/Users/alice/Documents/Develop/PythonCode/alicescrapy.csv'
2019-04-20 11:13:58 [scrapy.core.engine] INFO: Closing spider (finished)
2019-04-20 11:13:58 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 554,
'downloader/request_count': 2,
'downloader/request_method_count/GET': 2,
'downloader/response_bytes': 10981,
'downloader/response_count': 2,
'downloader/response_status_count/200': 2,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2019, 4, 20, 3, 13, 58, 885429),
'log_count/DEBUG': 2,
'log_count/ERROR': 1,
'log_count/INFO': 7,
'log_count/WARNING': 1,
'memusage/max': 65769472,
'memusage/startup': 65769472,
'response_received_count': 2,
'robotstxt/request_count': 1,
'robotstxt/response_count': 1,
'robotstxt/response_status_count/200': 1,
'scheduler/dequeued': 1,
'scheduler/dequeued/memory': 1,
'scheduler/enqueued': 1,
'scheduler/enqueued/memory': 1,
'spider_exceptions/ValueError': 1,
'start_time': datetime.datetime(2019, 4, 20, 3, 13, 58, 384500)}
2019-04-20 11:13:58 [scrapy.core.engine] INFO: Spider closed (finished)
爬虫运行后会生成一个alicescapy.xlsx的文件,打开内容如下: