文字分類(二):scrapy爬取網易新聞
文字分類的第一項應該就是獲取文字了吧。
在木有弄懂scrapy的情況下寫的,純應用,或許後續會補上scrapy的原理。
首先說一下我的環境:ubuntu14.10
scrapy安裝指南(肯定官網的最權威了):[傳送門](http://scrapy-chs.readthedocs.org/zh_CN/0.24/intro/install.html#intro-install)
需要完成的任務:
- 建立一個Scrapy專案
- 定義提取的Item
- 編寫爬取網站的Spider並提取Item
- 編寫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