最近热播的电视剧 《全职高手》是由小说改编而成的,爬取小说当作练习吧~~本文练习爬取第一章的章节标题和章节内容,而且保存到本地文件中。
$ scrapy init first_scrapy
建立完成后目录结构跟下面👇应该是同样的,在 spiders 目录下新建 novel.py 文件,待会咱就在这个文件中写爬虫程序。css
import scrapy class NovelSpider(scrapy.Spider): # 启动爬虫时会用到这个名称 name = "novel" # 爬取哪一个网页的源码,这里是网址 start_urls = ["https://www.biquge5200.cc/0_857/651708.html"] def parse(self, response): # 拿到 html 网页源代码 html_str = response.css('html').extract_first() # 保存为本地文件 source.html with open('source.html', 'w') as f: f.write(html_str) self.log('保存文件成功')
运行爬虫html
$ scrapy crawl novel <= 这里的 novel 就是上面代码中的 name 值
执行完成后在根目录下建立了 source.html 文件,打开能够看到网页的源代码已经被咱们爬下来了。python
Scrapy 提供调试环境和 css 提取器,帮助咱们快速准确的从 html 源代码中拿到咱们须要的数据。shell
Scrapy 提供了调试环境,方便咱们测试提取的数据是否正确。数组
命令行中输入👇脚本,其中 scrapy shell 是固定写法,后面跟要爬取网页的网址。bash
$ scrapy shell https://www.biquge5200.cc/0_857/651708.html
输入完成后会 blala... 打印一堆东东,咱们只要关注最后一行 >>>
。cookie
2019-08-01 09:22:29 [scrapy.utils.log] INFO: Scrapy 1.5.1 started (bot: scrapybot) 2019-08-01 09:22:29 [scrapy.utils.log] INFO: Versions: lxml 4.2.5.0, libxml2 2.9.8, cssselect 1.0.3, parsel 1.5.0, w3lib 1.19.0, Twisted 18.7.0, Python 3.7.0 (default, Sep 18 2018, 18:47:22) - [Clang 9.1.0 (clang-902.0.39.2)], pyOpenSSL 18.0.0 (OpenSSL 1.1.0i 14 Aug 2018), cryptography 2.3.1, Platform Darwin-17.7.0-x86_64-i386-64bit 2019-08-01 09:22:29 [scrapy.crawler] INFO: Overridden settings: {'DUPEFILTER_CLASS': 'scrapy.dupefilters.BaseDupeFilter', 'LOGSTATS_INTERVAL': 0} 2019-08-01 09:22:29 [scrapy.middleware] INFO: Enabled extensions: ['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.memusage.MemoryUsage'] 2019-08-01 09:22:29 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2019-08-01 09:22:29 [scrapy.middleware] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2019-08-01 09:22:29 [scrapy.middleware] INFO: Enabled item pipelines: [] 2019-08-01 09:22:29 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023 2019-08-01 09:22:29 [scrapy.core.engine] INFO: Spider opened 2019-08-01 09:22:29 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.biquge5200.cc/0_857/651708.html> (referer: None) [s] Available Scrapy objects: [s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc) [s] crawler <scrapy.crawler.Crawler object at 0x10bc049e8> [s] item {} [s] request <GET https://www.biquge5200.cc/0_857/651708.html> [s] response <200 https://www.biquge5200.cc/0_857/651708.html> [s] settings <scrapy.settings.Settings object at 0x10bc04748> [s] spider <DefaultSpider 'default' at 0x10bf0ac88> [s] Useful shortcuts: [s] fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed) [s] fetch(req) Fetch a scrapy.Request and update local objects [s] shelp() Shell help (print this help) [s] view(response) View response in a browser >>>
好比咱们想提取 https://www.biquge5200.cc/0_857/651708.html
的 title 标签中的数据,在最后一行 >>>
后面输入 response.css('title'),而后回车。scrapy
>>> response.css('title') [<Selector xpath='descendant-or-self::title' data='<title>第一章 被驱逐的高手_全职高手_笔趣阁</title>'>]
你会发现,提取到的是个 Selector 数组,并非咱们想要的数据。Scrapy 给咱们准备了一些函数来进一步提取,extract() 函数将 Selector 转换为咱们熟悉的 html 标签ide
>>> response.css('title').extract() ['<title>第一章 被驱逐的高手_全职高手_笔趣阁</title>']
👆拿到的 html 标签仍然是一个数组,在后面加上 [0] 很方便拿到数组中第一个元素函数
>>> response.css('title').extract()[0] '<title>第一章 被驱逐的高手_全职高手_笔趣阁</title>'
Scrapy 提供了另外一个函数 extract_first(),一样能够拿到数组中第一个元素,写法上更加简单。至此,成功提取到 title 标签,可是多了 title 标签,继续修改。
>>> response.css('title').extract_first() '<title>第一章 被驱逐的高手_全职高手_笔趣阁</title>'
在 title 后面加上 ::text 便可提取 html 标签包裹的内容了。到这里已经成功提取到咱们须要的数据了。
>>> response.css('title::text').extract_first() '第一章 被驱逐的高手_全职高手_笔趣阁'
::text 能够提取 html 标签包裹的内容,若是要提取 html 标签自身的属性,好比上面👇 a 标签的 href 属性值,怎么办呢?
<a href="https://xxx.yyy.ccc">连接</a>
::attr(属性名) 能够提取 html 标签自身的属性。
>>> response.css('a::attr(href)').extract_first()
有了前面 css 提取器的学习,拿到章节标题和章节内容相信不是什么困难的事了~~
import scrapy class NovelSpider(scrapy.Spider): name = "novel" start_urls = ["https://www.biquge5200.cc/0_857/651708.html"] def parse(self, response): # 拿到章节标题 title = response.css('div.bookname h1::text').extract_first() # 拿到章节内容 content = '\n\n'.join(response.css('div#content p::text').extract()) print("title ", title) print("content ", content)
运行爬虫
$ scrapy crawl novel
能够看到分别打印了章节标题和标题内容。
在第一步 爬取网页
中已经用过一次保存为本地文件的操做了,当时是把网页源代码保存为 source.html。
如今把章节标题和章节内容保存为 novel.txt 文件。
import scrapy class NovelSpider(scrapy.Spider): name = "novel" start_urls = ["https://www.biquge5200.cc/0_857/651708.html"] def parse(self, response): title = response.css('div.bookname h1::text').extract_first() content = '\n\n'.join(response.css('div#content p::text').extract()) # 保存为本地文件 novel.txt with open('novel.txt', 'w') as f: f.write(title) f.write('\n') f.write(content) self.log('保存文件成功')
运行爬虫,能够看到根目录下输出了 novel.txt 文件,成功地将章节标题和章节内容保存到文件中。