Scrapy 入门
1. 第一个爬虫
以下是官方文档的第一个爬虫例子。可以看到和我们手动使用request库和BeautifulSoup解析网页内容不同,Scrapy专门抽象了一个爬虫父类,我们只需要重写其中的方法,就可以迅速得到一个可以不断爬行的爬虫。
1 | import scrapy |
上面的爬虫有几个地方需要解释一下:
- 爬虫类的name属性,用来标识爬虫,该名字在一个项目必须是唯一的。
- start_requests()
方法,必须返回一个可迭代的列表(可以是列表,也可以是生成器),Scrapy会从这些请求开始抓取网页。 - parse()
方法,用于从网页文本中抓取相应内容,我们需要根据自己的需要重写该方法。
在上面的例子中使用start_requests()方法来设置起始URL,如果只需要简单指定URL还可以使用另一种简便方法,那就是设置类属性start_urls,Scrapy会读取该属性来设置起始URL。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'http://quotes.toscrape.com/page/1/',
'http://quotes.toscrape.com/page/2/',
]
def parse(self, response):
page = response.url.split("/")[-2]
filename = 'quotes-%s.html' % page
with open(filename, 'wb') as f:
f.write(response.body)
运行爬虫1
2scrapy list # 查看可运行的爬虫
scrapy crawl quotes # 运行爬虫,根据上述代码,将爬取网页源代码到文件。
修改parse方法的内容,提取页面有效信息1
2
3
4
5
6
7def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').extract_first(),
'author': quote.css('small.author::text').extract_first(),
'tags': quote.css('div.tags a.tag::text').extract_first()
}
存储提取的数据
1 | scrapy crawl quotes -o quotes.json # 生成json文件,并将数据json序列化 |
但是,当多次执行上述命令时,不会覆盖原数据,会追加数据到文件中,因此会形成一个破损的json文件。
可以使用其他格式,如json行1
scrapy crawl quotes -o quote1.jl
该JSON行格式是有用的,因为它的流状,你可以很容易地新记录追加到它。当您运行两次时,它没有JSON相同的问题。另外,由于每条记录都是一条独立的行,因此您可以处理大文件,而不必将所有内容都放在内存中,而像JQ这样的工具可以帮助在命令行执行该操作。
设置编码
如果不设置编码格式,会发现导出的所有汉字全变成了Unicode字符(类似\uA83B这样的)。自Scrapy1.2 起,增加了FEED_EXPORT_ENCODING属性,用于设置输出编码。我们在settings.py中添加下面的配置即可。1
FEED_EXPORT_ENCODING = 'utf-8'
2. 页面跳转-爬虫
首先先获取下一页的链接。1
2response.css('ul.pager li.next a::attr(href)').extract_first()
# 结果:'/page/2/'
获取页面跳转的爬虫1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = ['http://quotes.toscrape.com/page/1/']
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').extract_first(),
'author': quote.css('small.author::text').extract_first(),
'tags': quote.css('div.tags a.tag::text').extract_first()
}
next_page = response.css('ul.pager li.next a::attr(href)').extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
# 直接获取到下一页的绝对url,yield一个新Request对象
yield scrapy.Request(next_page, callback=self.parse)
在函数体中,使用yield表达式,可以是函数成为一个生成器。当调用生成器函数时,它将返回一个称为生成器的迭代器
现在,在提取数据之后,该parse()方法查找到下一页的链接,使用该urljoin()方法构建一个完整的绝对URL (因为链接可以是相对的),并产生一个新的请求到下一个页面,注册为回调来处理提取下一页的数据并保持所有页面的爬行。
也可以用response.follow()来获取链接。传入的对象只能是str或selector,不能使SelectorList
1 | # 方式一:不用获取到绝对的url,使用follow方法会自动帮我们实现 |
1 | # 方式二:只需要传入href这个selector |
1 | # 方式三:传递一个a的selector,follow方法自动会提取href |
使用Splider参数
-a 运行时,可以使用该选项向Splider提供命令行参数
这些参数被传递给Splider的_ init _方法,并默认成为蜘蛛属性。
在这个例子中,为参数提供的值tag将可以通过self.tag。你可以使用它来让你的蜘蛛只用特定的标签来获取引号,根据参数构建URL:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
def start_requests(self):
url = 'http://quotes.toscrape.com/'
tag = getattr(self, 'tag', None)
if tag is not None:
url = url + 'tag/' + tag
yield scrapy.Request(url, self.parse)
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').extract_first(),
'author': quote.css('small.author::text').extract_first(),
}
next_page = response.css('li.next a::attr(href)').extract_first()
if next_page is not None:
yield response.follow(next_page, self.parse)
运行命令:scrapy crawl quotes -o tag.json -a tag=love
点关注,不迷路
好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才。
白嫖不好,创作不易。各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !
原文作者: create17
原文链接: https://841809077.github.io/2018/05/26/Scrapy/Scrapy-入门.html
版权声明: 转载请注明出处(码字不易,请保留作者署名及链接,谢谢配合!)