这篇文章我们通过一个比较完整的例子来教你使用Scrapy,我选择爬取虎嗅网首页的新闻列表。
这里我们将完成如下几个步骤:
- 创建一个新的Scrapy工程
- 定义你所需要要抽取的Item对象
- 编写一个spider来爬取某个网站并提取出所有的Item对象
- 编写一个Item Pipline来存储提取出来的Item对象
Scrapy使用Python语言编写,如果你对这门语言还不熟,请先去学习下基本知识。
创建Scrapy工程
在任何你喜欢的目录执行如下命令
scrapy startproject coolscrapy
将会创建coolscrapy文件夹,其目录结构如下:
coolscrapy/
scrapy.cfg # 部署配置文件
coolscrapy/ # Python模块,你所有的代码都放这里面
__init__.py
items.py # Item定义文件
pipelines.py # pipelines定义文件
settings.py # 配置文件
spiders/ # 所有爬虫spider都放这个文件夹下面
__init__.py
...
定义我们的Item
我们通过创建一个scrapy.Item类,并定义它的类型为scrapy.Field的属性, 我们准备将虎嗅网新闻列表的名称、链接地址和摘要爬取下来。
import scrapy
class 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
import scrapy
from coolscrapy.items import CoolscrapyItem
class HuxiuSpider(scrapy.Spider):
name = 'huxiu'
allowed_domains = ['www.huxiu.com']
start_urls = ['https://www.huxiu.com/index.php/']
def parse(self, response):
cl=response.xpath('//div[@class="mod-info-flow"]/div/div[contains(@class,"mob-ctt")]')
for sel in cl:
item = CoolscrapyItem()
item['title'] = sel.xpath('h2/a/text()').extract_first()
item['link'] = sel.xpath('h2/a/@href').extract_first()
url = response.urljoin(item['link'])
item['desc'] = sel.xpath('div[@class="mob-sub"]/text()').extract_first()
print(item['title'],item['link'],item['desc'])
运行爬虫
在根目录执行下面的命令,其中huxiu是你定义的spider名字:
scrapy crawl huxiu
如果一切正常,应该可以打印出每一个新闻
处理链接
如果想继续跟踪每个新闻链接进去,看看它的详细内容的话,那么可以在parse()方法中返回一个Request对象, 然后注册一个回调函数来解析新闻详情。现在parse只提取感兴趣的链接,然后将链接内容解析交给另外的方法去处理了。 你可以基于这个构建更加复杂的爬虫程序了。
# -*- coding: utf-8 -*-
import scrapy
from coolscrapy.items import CoolscrapyItem
class HuxiuSpider(scrapy.Spider):
name = 'huxiu'
allowed_domains = ['www.huxiu.com']
start_urls = ['https://www.huxiu.com/index.php/']
def parse(self, response):
cl=response.xpath('//div[@class="mod-info-flow"]/div/div[contains(@class,"mob-ctt")]')
for sel in cl:
item = CoolscrapyItem()
item['title'] = sel.xpath('h2/a/text()').extract_first()
item['link'] = sel.xpath('h2/a/@href').extract_first()
url = response.urljoin(item['link'])
item['desc'] = sel.xpath('div[@class="mob-sub"]/text()').extract_first()
yield scrapy.Request(url, callback=self.parse_article)
def parse_article(self, response):
detail = response.xpath('//div[@class="article-wrap"]')
item = CoolscrapyItem()
item['title'] = detail.xpath('string(h1)').extract_first().strip()
item['link'] = response.url
item['posttime'] = detail.xpath(
'div[@class="article-author"]/div[@class="column-link-box"]/span[1]/text()').extract_first()
print(item['title'],item['link'],item['posttime'])
yield item
导出抓取数据
最简单的保存抓取数据的方式是使用json格式的文件保存在本地,像下面这样运行:
import json
import codecs
class CoolscrapyPipeline(object):
def __init__(self):
self.file = codecs.open('huxiu.json', 'wb',encoding='utf-8')
def process_item(self, item, spider):
line = json.dumps(dict(item),ensure_ascii=False) + '\n'
self.file.write(line)
return item
scrapy crawl huxiu
在演示的小系统里面这种方式足够了。不过如果你要构建复杂的爬虫系统, 最好自己编写Item Pipeline。
那么所有新闻的文章都存储到Json去了。
本篇文章转载自 https://www.xncoding.com/2016/03/10/scrapy-02.html