话不多说,撸它
1. 创建项目
scrapy startproject project
2. 创建Spider
cd projiect
scrapy genspider books book.toscrape.com
3. 运行爬虫
scrapy crawl books
4. spider文件
# -*- coding: utf-8 -*-
import scrapy
class QuotesSpider(scrapy.Spider):
#name:它是每个项目唯一的名字,用来区分不同的Spider
name = 'books'
#它是允许爬取的域名,如果初始或后序的请求链接不是这个域名下的,请求链接会被过滤掉
allowed_domains = ['book.toscrape.com']
#它包含了Spider在启动时爬取的url列表,初始请求是由它来定义的
start_urls = ['http://book.toscrape.com/']
'''Spider的一个方法,默认情况下,被调用时 start_urls 里面的链接构成的请求完
成下载执行后,返回的响应就会作为唯一的参数传递给这个函数 。 该方法负责解析返回的响
应、提取数据或者进一步生成要处理的请求。'''
def parse(self, response):
# 提取数据
# 每一本书的信息是在<article class="product_pod">中,我们使用
# css()方法找到所有这样的article 元素,并依次迭代
for book in response.css('article.product_pod'):
name = book.xpath('./h3/a/@title').extract_first()
price = book.css('p.price_color::text').extract_first()
yield {
'name': name,
'price': price,
}
next_url = response.css('ul.pager li.next a::attr(href)').extract_first()
if next_url:
# 如果找到下一页的url,得到绝对路径,构造新的Request 对象
next_url = response.urljoin(next_url)
yield scrapy.Request(next_url, callback=self.parse)
-
实际上,对于起始爬取点的下载请求是由Scrapy引擎调用Spider对象的start_requests方法提交的,由于BooksSpider类没有实现start_requests方法,因此引擎会调用Spider基类的start_requests方法。
-
在start_requests方法中,self.start_urls便是我们定义的起始爬取点列表(通过实例访问类属性),对其进行迭代,用迭代出的每个url作为参数调用make_requests_from_url方法。
-
在make_requests_from_url方法中,我们找到了真正构造Reqeust对象的代码,仅使用url和dont_filter参数构造Request对象。
-
由于构造Request对象时并没有传递callback参数来指定页面解析函数,因此默认将parse方法作为页面解析函数。此时BooksSpider必须实现parse方法,否则就会调用Spider基类的parse方法,从而抛出NotImplementedError异常(可以看作基类定义了一个抽象接口)。
-
起始爬取点可能有多个,start_requests方法需要返回一个可迭代对象(列表、生成器等),其中每一个元素是一个Request对象。这里,start_requests方法被实现成一个生成器函数(生成器对象是可迭代的),每次由yield语句返回一个Request对象。
1). 覆盖基类Spider的start_requests方法
在某些场景下使用这种方式更加灵活,例如有时想为Request添加特定的HTTP请求头部,或想为Request指定特定的页面解析函数。
import scrapy
class BooksSpider(scrapy.Spider):
name = 'books'
allowed_domains = ['book.toscrape.com']
# 实现start_requests 方法, 替代start_urls类属性
def start_requests(self):
yield scrapy.Request('http://books.toscrape.com/',
callback=self.parse_book,
headers={'User-Agent': 'Mozilla/5.0'},
dont_filter=True)
# 改用parse_book 作为回调函数
def parse_book(self, response):
pass
2). 实现页面解析函数
- 使用选择器提取页面中的数据,将数据封装后(Item或字典)提交给Scrapy引擎。
- 使用选择器或LinkExtractor提取页面中的链接,用其构造新的Request对象并提交给Scrapy引擎(下载链接页面)。
(未写完...有空更新)
网友评论