开始学 python 的 Scrapy 框架了,参考书是崔庆才的《python3 网络爬虫开发实战》
跟着示例敲完之后,又试着按照一样的逻辑去爬取了 B 站排行榜的数据。
通过这个小项目学习使用 Scrapy 框架。
步骤
新建项目
首先新建一个名为practice
的项目
1
| $scrapy startproject practice
|
这个项目的目录结构(省略 init 文件):
- practice
- practice
- items.py
- middlewares.py
- pipelines.py
- settings.py
- scrapy.cfg
这一个项目里面的代码是整个项目的爬虫通用的。
新建 Spider
新建一个爬虫bilibiliRank
1 2
| $cd practice $scrapy genspider bilibiliRank
|
然后与在此目录下出现了一个spider
文件夹,用于存放这个新的爬虫
bilibiliRank.py
中:
1 2 3 4 5 6 7 8 9
| import scrapy
class BilibilirankSpider(scrapy.Spider): name = 'bilibiliRank' allowed_domains = ['bilibili.com'] start_urls = ['https://www.bilibili.com/ranking/']
def parse(self, response): pass
|
spider
文件夹里面是用于爬取不同网站的爬虫,它继承自scrapy.Spider
,scrapy 的引擎Engine
就是利用你写的爬虫里面的parse()
方法来解析页面获取数据,可以在这个方法里面将数据以item
的形式返回出去,给ItemPipeline
继续处理。
创建 Item
items.py
里面定义了不同的 item,这些 item 都继承自scrapy.Item
,文件生成的内容如下(无关注释已删去):
1 2 3 4 5 6
| import scrapy
class PracticeItem(scrapy.Item): pass
|
在这里你可以照着它的模板新建一个类,也可以直接修改,总之只要符合要求就可以:
1 2 3 4 5 6 7 8
| import scrapy
class RankItem(scrapy.Item): num=scrapy.Field() title=scrapy.Field()
|
在这个 Item 子类当中,我新建了两个域,也可以说是字段。按照注释给出的格式来就可以了。
解析 response
适当简化的流程大概是:引擎利用爬虫的start_url
发起请求,然后将得到的响应response
作为参数传入爬虫的parse()
方法中。parse()
将解析出的数据装入Item
并返回给引擎。
需要解析的 html 页面内容(只展示其中一个项的结构):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <ul class="rank-list"> <li class="rank-item"> <div class="num">1</div> <div class="content"> <div class="img"> <a href="//www.bilibili.com/video/av56121331/" target="_blank"> <div class="lazy-img cover"> <img alt="视频标题" src="图片url" /> </div> </a> <div class="watch-later-trigger w-later"></div> </div> <div class="info"> <a href="视频url" target="_blank" class="title">视频标题</a > <div class="detail"> <span class="data-box"> <i class="b-icon play"></i>366.8万</span> <span class="data-box"><i class="b-icon view"></i>3.8万</span> <a target="_blank" href="视频url"> <span class="data-box"> <i class="b-icon author"></i>作者名</span ></a > </div> <div class="pts"> <div>3798978</div> 综合得分 </div> </div> </div> </li> </ul>
|
爬虫文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import scrapy from practice.items import RankItem
class BilibilirankSpider(scrapy.Spider): name = 'bilibiliRank' allowed_domains = ['bilibili.com'] start_urls = ['https://www.bilibili.com/ranking/']
def parse(self, response): rank_items=response.css('.rank-list .rank-item') for rank_item in rank_items: item=RankItem() item['num']=rank_item.css('.num::text').extract_first() item['title']=rank_item.css('.content .info .title::text').extract_first() yield item
|
遇到的问题:
- 注意获取的所有项目得是一个节点,不能用
extract()
读取其中的数据,第一次写时,写成了:
1 2 3
| rank_list=response.css('.rank-item').extract() for rank_item in rank_list:
|
爬取
1
| $scrapy crawl bilibiliRank -o bilibiliRank.json
|
利用名为bilibiliRank
爬虫进行爬取,并将得到的结果保存在bilibiliRank.json
文件中
参考链接