这篇文章我们通过一个比较完整的例子来教你使用Scrapy,我选择爬取虎嗅网首页 的新闻列表。
这里我们将完成如下几个步骤:
创建一个新的Scrapy工程
定义你所需要要抽取的Item对象
编写一个spider来爬取某个网站并提取出所有的Item对象
编写一个Item Pipline来存储提取出来的Item对象
Scrapy使用Python语言编写,如果你对这门语言还不熟,请先去学习下基本知识。
创建Scrapy工程 在任何你喜欢的目录执行如下命令
1 scrapy startproject coolscrapy
将会创建coolscrapy文件夹,其目录结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 coolscrapy/ scrapy.cfg # 部署配置文件 coolscrapy/ # Python模块,你所有的代码都放这里面 __init__.py items.py # Item定义文件 pipelines.py # pipelines定义文件 settings.py # 配置文件 spiders/ # 所有爬虫spider都放这个文件夹下面 __init__.py ...
定义我们的Item 我们通过创建一个scrapy.Item类,并定义它的类型为scrapy.Field的属性,
我们准备将虎嗅网新闻列表的名称、链接地址和摘要爬取下来。
1 2 3 4 5 6 7 import scrapyclass HuxiuItem (scrapy.Item): title = scrapy.Field() link = scrapy.Field() desc = scrapy.Field() posttime = scrapy.Field()
也许你觉得定义这个Item有点麻烦,但是定义完之后你可以得到许多好处,这样你就可以使用Scrapy中其他有用的组件和帮助类。
第一个Spider 蜘蛛就是你定义的一些类,Scrapy使用它们来从一个domain(或domain组)爬取信息。
在蜘蛛类中定义了一个初始化的URL下载列表,以及怎样跟踪链接,如何解析页面内容来提取Item。
定义一个Spider,只需继承scrapy.Spider
类并定于一些属性:
name: Spider名称,必须是唯一的
start_urls: 初始化下载链接URL
parse(): 用来解析下载后的Response对象,该对象也是这个方法的唯一参数。
它负责解析返回页面数据并提取出相应的Item(返回Item对象),还有其他合法的链接URL(返回Request对象)。
我们在coolscrapy/spiders文件夹下面新建huxiu_spider.py
,内容如下:
huxiu_spider.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 """ Topic: sample Desc : """ from coolscrapy.items import HuxiuItemimport scrapyclass HuxiuSpider (scrapy.Spider): name = "huxiu" allowed_domains = ["huxiu.com" ] start_urls = [ "http://www.huxiu.com/index.php" ] def parse (self, response ): for sel in response.xpath('//div[@class="mod-info-flow"]/div/div[@class="mob-ctt"]' ): item = HuxiuItem() item['title' ] = sel.xpath('h3/a/text()' )[0 ].extract() item['link' ] = sel.xpath('h3/a/@href' )[0 ].extract() url = response.urljoin(item['link' ]) item['desc' ] = sel.xpath('div[@class="mob-sub"]/text()' )[0 ].extract() print (item['title' ],item['link' ],item['desc' ])
运行爬虫 在根目录执行下面的命令,其中huxiu是你定义的spider名字:
如果一切正常,应该可以打印出每一个新闻
处理链接 如果想继续跟踪每个新闻链接进去,看看它的详细内容的话,那么可以在parse()方法中返回一个Request对象,
然后注册一个回调函数来解析新闻详情。
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 from coolscrapy.items import HuxiuItemimport scrapyclass HuxiuSpider (scrapy.Spider): name = "huxiu" allowed_domains = ["huxiu.com" ] start_urls = [ "http://www.huxiu.com/index.php" ] def parse (self, response ): for sel in response.xpath('//div[@class="mod-info-flow"]/div/div[@class="mob-ctt"]' ): item = HuxiuItem() item['title' ] = sel.xpath('h3/a/text()' )[0 ].extract() item['link' ] = sel.xpath('h3/a/@href' )[0 ].extract() url = response.urljoin(item['link' ]) item['desc' ] = sel.xpath('div[@class="mob-sub"]/text()' )[0 ].extract() yield scrapy.Request(url, callback=self.parse_article) def parse_article (self, response ): detail = response.xpath('//div[@class="article-wrap"]' ) item = HuxiuItem() item['title' ] = detail.xpath('h1/text()' )[0 ].extract() item['link' ] = response.url item['posttime' ] = detail.xpath( 'div[@class="article-author"]/span[@class="article-time"]/text()' )[0 ].extract() print (item['title' ],item['link' ],item['posttime' ]) yield item
现在parse只提取感兴趣的链接,然后将链接内容解析交给另外的方法去处理了。
你可以基于这个构建更加复杂的爬虫程序了。
导出抓取数据 最简单的保存抓取数据的方式是使用json格式的文件保存在本地,像下面这样运行:
1 scrapy crawl huxiu -o items.json
在演示的小系统里面这种方式足够了。不过如果你要构建复杂的爬虫系统,
最好自己编写Item Pipeline 。
保存数据到数据库 上面我们介绍了可以将抓取的Item导出为json格式的文件,不过最常见的做法还是编写Pipeline将其存储到数据库中。
我们在coolscrapy/pipelines.py
定义
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 34 35 36 37 38 import datetimeimport redisimport jsonimport loggingfrom contextlib import contextmanagerfrom scrapy import signalsfrom scrapy.exporters import JsonItemExporterfrom scrapy.pipelines.images import ImagesPipelinefrom scrapy.exceptions import DropItemfrom sqlalchemy.orm import sessionmakerfrom coolscrapy.models import News, db_connect, create_news_table, Articleclass ArticleDataBasePipeline (object ): """保存文章到数据库""" def __init__ (self ): engine = db_connect() create_news_table(engine) self.Session = sessionmaker(bind=engine) def open_spider (self, spider ): """This method is called when the spider is opened.""" pass def process_item (self, item, spider ): a = Article(url=item["url" ], title=item["title" ].encode("utf-8" ), publish_time=item["publish_time" ].encode("utf-8" ), body=item["body" ].encode("utf-8" ), source_site=item["source_site" ].encode("utf-8" )) with session_scope(self.Session) as session: session.add(a) def close_spider (self, spider ): pass
上面我使用了python中的SQLAlchemy来保存数据库,这个是一个非常优秀的ORM库,
我写了篇关于它的入门教程 ,可以参考下。
然后在setting.py
中配置这个Pipeline,还有数据库链接等信息:
1 2 3 4 5 6 7 8 9 10 11 12 ITEM_PIPELINES = { 'coolscrapy.pipelines.ArticleDataBasePipeline' : 5 , } DATABASE = {'drivername' : 'mysql' , 'host' : '192.168.203.95' , 'port' : '3306' , 'username' : 'root' , 'password' : 'mysql' , 'database' : 'spider' , 'query' : {'charset' : 'utf8' @@
再次运行爬虫
那么所有新闻的文章都存储到数据库中去了。
下一步 本章只是带你领略了scrapy最基本的功能,还有很多高级特性没有讲到。接下来会通过多个例子向你展示scrapy的其他特性,然后再深入讲述每个特性。