经过前面的学习,我们初识了 Scrapy 框架,通过 Scrapy 提供的互动工具,我们在命令行中体验了 Scrapy 中的 CSS 选择器
最重要的几个点是:. 代表 class,# 代表 id,比如 div.book 代表 class 包含 book 的 div 元素,div#book 代表 id 为 book 的 div 元素。在有层级关系时,用 > 号连接直接下一级的元素,用空格连接所有下级的元素。
这篇文章将带大家将走进 Scrapy,学习如何启动一个真正意义上的 Scrapy 项目。
和之前一样,我们 Win + R 打开 cmd 命令行,在命令行输入 scrapy 检查框架是否正常显示,然后我们再输入explorer . 打开执行命令所在的文件夹↓
注意:explorer 命令后面有一个点,这个点代表当前文件夹,同时要注意 explorer 命令和点之间有一个空格。
之后在命令行中输入下面的命令,让 Scrapy 创建一个名叫 appinn 项目:
scrapy startproject appinn
这时你会发现刚刚打开的文件夹里多了一个叫做 appinn 的文件夹,它的目录结构如下:
appinn
├── appinn # 项目代码所在的目录
│ ├── __init__.py
│ ├── items.py # 定义数据的格式
│ ├── middlewares.py
│ ├── pipelines.py # 处理数据、输出到文件等等
│ ├── settings.py # 一些设置
│ └── spiders # 爬虫所在的目录
│ └── __init__.py
└── scrapy.cfg
上面标红的就是需要大家留心的!
然后我们还需要在命令行里输入 cd appinn,进入 appinn 文件夹。
注意:下面的操作都需要保证命令行在项目里哦,如果出错,请先检查一下自己是不是在项目根目录里。
下面我们来跟随一个简单的项目实战,理解这些文件的作用
我们打开小众软件的 Windows 软件推荐页:https://www.appinn.com/category/windows/
然后随便打开一篇文章
这次我们要爬取的是 Windows 版面下所有文章的标题、时间、作者、分数、正文↓
接下来,我们来分别看看 Scrapy 生成的这些文件在爬虫中具体起到了什么作用。
items.py 是记录我们想要的数据格式的文件。
在确定了我们要爬的数据是什么之后,就可以来定义数据的格式。我们数据的格式可以定义在 items.py 里。创建项目时 Scrapy 给这个文件自动生成了如下的代码↓
我们利用编辑器打开 items.py 文件
import scrapy
class AppinnItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass
按照我们需要的数据标题、时间、作者、分数、正文,分别把他们叫做 title、time、author、score 和 content。于是把 items.py 文件里的代码改成这样↓
import scrapy
class Article(scrapy.Item):
title = scrapy.Field() # 标题
time = scrapy.Field() # 时间
author = scrapy.Field() # 作者
score = scrapy.Field() # 分数
content = scrapy.Field() # 内容
通过 scrapy.Field() 方法,我们定义出了所有需要的字段,这样就定义好了我们要的数据格式:一个叫做 Article 的 Item。Item 是一个和字典类似的东西,使用它而不用字典的理由就是:在爬取网页的时候常常出现数据缺失、内容错误之类的问题,使用 Item 可以更好的处理这些问题。
spiders 目录里保存了我们创建的爬虫。
在命令行里执行下面的命令并回车,它会帮我们创建一个叫做 article 的爬虫,并且只爬取 www.appinn.com 下的网页↓
scrapy genspider article www.appinn.com
执行成功后可以看到在 spiders 目录里多出了一个 article.py,文件里有自动生成的代码↓
import scrapy
class ArticleSpider(scrapy.Spider):
name = 'article'
allowed_domains = ['www.appinn.com']
start_urls = ['http://www.appinn.com/']
def parse(self, response):
pass
注意
name :是项目中每个爬虫唯一的名字,用来区分不同的爬虫。
allowed_domains :是允许爬取的域名,如果请求的链接不在这个域名下,那么这些请求将会被过滤掉。
start_urls :是初始请求地址的列表,也就是一开始就爬取的页面地址列表。
parse() :方法是默认的解析方法,负责解析返回的响应、提取数据或者生成下一步要处理的请求。
现在我先把代码进行拆分说明!后面会有完整代码!
首先我们把 start_urls 改成我们需要的开始链接↓
start_urls = ['https://www.appinn.com/category/windows/']
接着引入我们刚刚写好的 Items.py↓
from appinn.items import Article
下面是加一个解析文章的方法,用来解析文章详情页(如:https://www.appinn.com/videocutter-and-mp3cutter-yyzsoft/),把标题、时间、作者、分数、正文取出来。我们把这个方法叫做 parse_article,具体代码如下↓
def parse_article(self, response):
article = Article()
# 从 response 里提取出标题、时间、作者、分数和内容
# 并将它们都存到 article 这个 item 里
article['title'] = response.css('h1.title::text').get()
article['time'] = response.css('span.thetime span::text').get()
article['author'] = response.css('span.theauthor span a::text').get()
article['score'] = response.css('em strong::text').get()
contents = response.css('div.post-single-content *::text').getall()
article['content'] = '\n'.join(contents)
# 给出结果
yield article
注意:上一篇中我们介绍过 yield,它和 return 类似,但不会结束函数或方法,而能够多次返回内容。
然后是默认的解析方法 parse(),我们用它来解析列表页↓
def parse(self, response):
# 找到所有文章的链接,通知 Scrapy 用 parse_article 方法解析
for article_url in response.css('article h2.title a::attr(href)').getall():
if not article_url:
continue
# 后续请求和解析
yield response.follow(article_url, self.parse_article)
# 找到下一页的链接,通知 Scrapy 用 parse 方法解析
next_page = response.css('a.next::attr(href)').get()
if next_page:
# 后续请求和解析
yield response.follow(next_page, self.parse)
response.follow() 方法用于生成下一个请求和数据解析,第一个参数是下一个页面的地址,第二个是用于解析从第一个参数地址获取到网页源代码数据的方法。上面解析文章用了 parse_article() 方法,解析文章列表页用了 parse() 方法。
到这里,我们 spiders 目录里的爬虫就写好了。完整版的 article.py 如下↓
import scrapy
from appinn.items import Article
class ArticleSpider(scrapy.Spider):
name = 'article'
allowed_domains = ['www.appinn.com']
start_urls = ['https://www.appinn.com/category/windows/']
def parse(self, response):
# 找到所有文章的链接,通知 Scrapy 用 parse_article 方法解析
for article_url in response.css('article h2.title a::attr(href)').getall():
if not article_url:
continue
# 后续请求和解析
yield response.follow(article_url, self.parse_article)
# 找到下一页的链接,通知 Scrapy 用 parse 方法解析
next_page = response.css('a.next::attr(href)').get()
if next_page:
# 后续请求和解析
yield response.follow(next_page, self.parse)
def parse_article(self, response):
article = Article()
# 从 response 里提取出标题、时间、作者、分数和内容
# 并将它们都存到 article 这个 item 里
article['title'] = response.css('h1.title::text').get()
article['time'] = response.css('span.thetime span::text').get()
article['author'] = response.css('span.theauthor span a::text').get()
article['score'] = response.css('em strong::text').get()
contents = response.css('div.post-single-content *::text').getall()
article['content'] = '\n'.join(contents)
# 给出结果
yield article
parse() 方法每次执行时都要完成下面这两件事↓
找到当前页面中所有文章的链接,生成解析请求,Scrapy 会用 parse_article() 方法解析文章链接;
找到下一个页面的链接,生成解析请求,Scrapy 会用 parse() 方法解析它找到的文章列表链接。
pipelines.py 文件允许我们在得到结果之后,对结果进行一些处理。比如我们不想要分数在 3 以下的文章,就可以在 pipelines.py 里面做处理。
Scrapy 替我们自动生成的代码如下,默认会直接 return item,意思是保留所有的 item↓
class AppinnPipeline(object):
def process_item(self, item, spider):
return item
这个 process_item() 方法就是得到结果之后处理 item 的方法,在这里做一些过滤或者对 item 做一些修改都是可以的。在这个方法里 raise DropItem() 可以去掉我们不想要的 item,所以我们把它改成下面这样来去掉 3 分以下的文章↓
from scrapy.exceptions import DropItem
class AppinnPipeline(object):
def process_item(self, item, spider):
if item.get('score'):
# 把 item 的 score 变成整数
item['score'] = int(item['score'])
if item['score'] < 3:
raise DropItem('去掉 3 分以下的文章')
return item
前面说过 item 和字典类似,你可以简单的认为 item 就是字典,使用 get() 方法可以获取其中的内容。当该键不存在时返回 None,而非报错。
settings.py 是整个项目的配置文件,这个文件里可以设置爬取并发个数、等待时间、输出格式、默认 headers 等等。
我们可以写一些配置如下↓
BOT_NAME = 'appinn'
SPIDER_MODULES = ['appinn.spiders']
NEWSPIDER_MODULE = 'appinn.spiders'
# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'appinn (+http://www.yourdomain.com)'
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
# 上面都是自动生成的,下面开始是我们自己定义的
# 要使用的 pipeline
ITEM_PIPELINES = {
'appinn.pipelines.AppinnPipeline': 300, # 300 表示顺序,pipeline 有多个时,数字越小越先执行
}
FEED_FORMAT = 'csv' # 最后输出的文件格式
FEED_URI = 'appin_windows_apps.csv' # 最后输出的文件名
# 为了避免对被爬网站造成太大的压力,我们启动自动限速,设置最大并发数为 5
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_TARGET_CONCURRENCY = 5
在命令行输入 scrapy crawl article 并回车,爬虫就开始运行了。由于我们在设置文件里配置了自动限速,所以我们稍等几分钟。
自动爬取过程↓
完成后我们可以在命令行里输入 explorer . 打开当前所在的 appinn 文件夹,这时我们可以找到一个名为 appin_windows_apps.csv 的文件,这就是最后的结果↓
本次分享到此结束,谢谢大家阅读!!