1. 程式人生 > >文字分類(二):scrapy爬取網易新聞

文字分類(二):scrapy爬取網易新聞

文字分類的第一項應該就是獲取文字了吧。
在木有弄懂scrapy的情況下寫的,純應用,或許後續會補上scrapy的原理。
首先說一下我的環境:ubuntu14.10
scrapy安裝指南(肯定官網的最權威了):[傳送門](http://scrapy-chs.readthedocs.org/zh_CN/0.24/intro/install.html#intro-install)

需要完成的任務:

  1. 建立一個Scrapy專案
  2. 定義提取的Item
  3. 編寫爬取網站的Spider並提取Item
  4. 編寫Item Pipeline來儲存提取到的Item

正式開始

新建scrapy專案

在命令列下:

scrapy startproject tech163

執行完程式後,將會有如下結構:

tech163/
    scrapy.cfg
    tech163/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...

定義item

開啟items.py
這裡寫圖片描述
news_thread: 定義獲取新聞的程序
news_title:獲取新聞標題
news_url:獲取新聞地址
news_time:獲取新聞釋出時間
news_from:獲取釋出者
from_url:獲取。。。
news_body:獲取新聞正文

定義spider

在spider目錄下新建news_spider.py。必須繼承scrapy.Spider類,且需要定義以下三個屬性:

  • name:用於區別Spider。該名字必須是唯一的。不可以為不同的Spider設定相同的名字。
  • start_url:包含了Spider在啟動時進行爬取的URL列表。因此,第一個被獲取的頁面將是其中之一。後續的url則是從出事的url獲取到的資料中提取。可以使用正則表示式定義和過濾需要進行跟進的連結。

  • parse():是spider的一個方法。被呼叫時,每個初始url完成下載後生成的response物件將會作為唯一的引數傳遞給該函式。該方法負責解析返回的資料、提取資料(生成item)以及生成需要進一步處理的url的response物件。

selectors選擇器

scrapy使用了一種基於XPath和CSS表示式機制:Scrapy Selectors。
我們使用XPath來從頁面的HTML原始碼中選擇需要提取的資料。簡單說一下XPath的用法。
  • /html/head/title:選擇HTML文件中<head>標籤內的<title>元素
  • /html/head/title/text():選擇上面提到的<title>元素的文字
  • //td:選擇所有的<td>元素
  • //div[@class=”mine”]:選擇所有具有class=“mine”元素(2015/12/4/21:37)

以一篇網易的科技類的新聞進行說明:新聞網址

這裡寫圖片描述
可以看到title是在head中的title中,因此使用XPath的形式為:/html/head/title/text()
其餘的提取內容類似,需要檢視網頁的原始碼。附上原始碼(只是爬取科技類的新聞,其餘的只要修改網址即可)

 #encoding: utf-8
    import scrapy
    import re
    from scrapy.selector import Selector
    from tech163.items import Tech163Item
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider,Rule
    class ExampleSpider(CrawlSpider):
        name = "news"
        allowed_domains = ["tech.163.com"] #需要對應網易新聞的類別
        start_urls = ['http://tech.163.com/']
        rules=(
            Rule(LinkExtractor(allow=r"/14/08\d+/\d+/*"), #這裡需根據具體年份考慮 /14/是指年份 /08\d+/ 是指月份 這個可參考一個網易新聞的地址:http://tech.163.com/16/1119/09/C67P02V400097U81.html 
            callback="parse_news",follow=True),
        )
        def printcn(suni):
            for i in uni:
                print uni.encode('utf-8')
        def parse_news(self,response):
            item = Tech163Item()
            item['news_thread']=response.url.strip().split('/')[-1][:-5]
            # self.get_thread(response,item)
            self.get_title(response,item)
            self.get_source(response,item)
            self.get_url(response,item)
            self.get_news_from(response,item)
            self.get_from_url(response,item)
            self.get_text(response,item)
            #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!remenber to Retrun Item after parse
            return item 
        def get_title(self,response,item):
            title=response.xpath("/html/head/title/text()").extract()
            if title:
                # print 'title:'+title[0][:-5].encode('utf-8')
                item['news_title']=title[0][:-5]

        def get_source(self,response,item):
            source=response.xpath("//div[@class='left']/text()").extract()
            if source:
                # print 'source'+source[0][:-5].encode('utf-8')
                item['news_time']=source[0][:-5]

        def get_news_from(self,response,item):
            news_from=response.xpath("//div[@class='left']/a/text()").extract()
            if news_from:
                # print 'from'+news_from[0].encode('utf-8')     
                item['news_from']=news_from[0]

        def get_from_url(self,response,item):
            from_url=response.xpath("//div[@class='left']/a/@href").extract()
            if from_url:
                # print 'url'+from_url[0].encode('utf-8')       
                item['from_url']=from_url[0]    

        def  get_text(self,response,item):
            news_body=response.xpath("//div[@id='endText']/p/text()").extract()
            if news_body:
                # for  entry in news_body:
                #   print entry.encode('utf-8')
                item['news_body']=news_body 
        def get_url(self,response,item):
            news_url=response.url
            if news_url:
                #print news_url 
            item['news_url']=news_url

定義Item Pipeline

在pipelin.py檔案中編寫自己的pipeline,簡單點說就是定義爬蟲爬取的內容存放的地方。

from scrapy import signals
from scrapy.exporters import XmlItemExporter
class Tech163Pipeline(object):
    def __init__(self):
        pass
    @classmethod
    def from_crawler(cls,crawler):
        pipeline = cls()
        crawler.signals.connect(pipeline.spider_opened,signals.spider_opened)
        crawler.signals.connect(pipeline.spider_closed,signals.spider_closed)
        return pipeline
    def spider_opened(self,spider):
        self.file = open("test.xml","wb")
        self.exporter = XmlItemExporter(self.file)
        self.exporter.start_exporting()
    def spider_closed(self,spider):
        self.exporter.finish_exporting()
        self.file.close()
    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item

在這裡採用xml形式進行資料的存放,資料也可以存放到資料庫中。

最後一步了,進行配置

萬里長城,終於只差一步。
這裡寫圖片描述

在這裡等我研究了在進行解釋。
最下邊的USER_AGENT是使用瀏覽器代理,防止被禁的。(2015/12/5 11:52)

忘了寫執行的命令了:
退到與工程同一目錄下:

scrapy crawl news