上次把scrapy環境配置好了,這次試着來做些實際的東西。
關於scrapy抓取網頁的文章已經有很多了,但大多數的內容已經過期,不再適用於最新的scrapy版本,故在此另作一文,記錄學習過程。
目標是一個政府網站,紅框內的部分。
思路很簡單:
有了url之後,用xpath表達式提取出來,再寫到文件裏即可
如果之前沒有scrapy的經驗,可以先看看這兩篇文章:
http://www.cnblogs.com/txw1958/archive/2012/07/16/scrapy-tutorial.html
教你快速上手一個scrapy項目
以及
http://www.ituring.com.cn/article/114408
教你從豆瓣上抓取電影信息
值得注意的是,第二篇文章裏的有些方法已經不推薦使用,這裏做了改進
talk is cheap,show me the code:
#coding=utf-8
import sys
from scrapy.spider import BaseSpider
from scrapy.selector import Selector
from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
import json
reload(sys)
sys.setdefaultencoding('utf8')
class DmozSpider(BaseSpider):
name = "dmoz"
allowed_domains=[""]
start_urls=["http://www.jjkjj.gov.cn/"]
def parse(self,response):
filename = response.url.split("/")[-2]
titles=[] titles.extend(response.selector.xpath('//div[@class ="Work_News_line"]/a/text()').extract())
open(filename,'w').write(json.dumps(titles, encoding="gb2312", ensure_ascii=False))
下面來分析代碼:
from scrapy.spider import BaseSpider
這裏是基於單個頁面的抓取,因此使用BaseSpider,基於鏈接跳轉的爬蟲可以看一下第二篇文章
name = "dmoz"
allowed_domains=[""]
start_urls=["http://www.jjkjj.gov.cn/"]
start_urls就是主域名,
因此allowed_domain設置爲空
def parse(self,response):
filename = response.url.split("/")[-2]
titles=[] titles.extend(response.selector.xpath('//div[@class ="Work_News_line"]/a/text()').extract())
這個markdown編輯器縮進有點問題,titles.extend…這一行應該和上面一行保持同一縮進,不然會報出
Python運行錯誤,raise notImplementedError
當遇到這種錯誤時,檢查下縮進,一般就能解決
接下來看xpath表達式,
具體含義爲:找到class屬性爲”Work_News_line”的div,其下面的<a>
標籤的值
extract()函數 返回一個unicode字符串,該字符串爲XPath選擇器返回的數據
關於xpath的使用,還有一些需要注意的地方
在上面第二篇文章中,使用xpath的方式是:
sel=Selector(response) item=DoubanmoiveItem() item['name']=sel.xpath('//[@id="content"]/h1/span[1]/text()').extract()
新版本的scrapy不建議這樣使用
因此我改成了上面的寫法
接下來是最頭疼的中文顯示問題了
在shell裏面看看xpath的查詢結果:
一堆Unicode字符,其實這樣也算抓取成功了,但基本上不可用,還是需要將其轉化成中文。
感覺scrapy,乃至python在字符集這一塊做得都不是很好,
再來看上面的代碼:
titles=[] titles.extend(response.selector.xpath('//div[@class ="Work_News_line"]/a/text()').extract())
這裏聲明瞭一個列表,每查詢到一個值,就將其放到列表裏,然後需要將這個列表轉成字符串寫入文件。
python本身提供了str()
方法,用於將任意對象轉換成字符串,但沒有對中文提供支持,轉出來的字符串還是unicode編碼。
具體見這篇帖子:str字符串轉化
有一種解決辦法是利用python自帶的json模塊
open(filename,'w').write(json.dumps(titles, encoding="gb2312", ensure_ascii=False))
這樣就ok
我們把抓到的數據寫到了文件裏面,下面看看結果: