用Scrapy抓取豆瓣小組數據(一)

  最近在coursera.org(在線學習平臺)上學SNA(Social Network Analysis,社交網絡分析)。有興趣的同窗能夠去看一眼:https://class.coursera.org/sna-002/,課程講的頗有意思,等回頭我上徹底部課程打算再寫下詳細總結和思考。 python

爲何要抓取豆瓣小組數據?

  課程要作一個帶編程的final project,大概內容就是本身找一個網絡數據集,而後按照課程中提供的方法進行分析。其實最難的部分是找數據,兩種方法:本身抓,或者是找現成的。對於後者,國內有個叫數據堂的數據分享網站作的不錯,上面有豆瓣,淘寶,微博等各類數據,不過有些數據須要收費;國外有個叫Konect的網站專一於複雜網絡數據。 shell

  看了一圈現成的數據都不太滿意,決定本身抓取了。目標鎖定豆瓣小組,打算分析小組之間的互相聯繫。 編程

如何用Scrapy抓取網頁?

還不太瞭解Scrapy的同窗直接看這裏http://www.oschina.net/p/scrapy,這邊就不贅述基本功能和安裝方式。 json

1,先創建一個scrapy項目,項目名稱doubanscrapy startproject douban 數組

scrapy startproject douban

會生成一個項目目錄,內部結構大概以下: cookie

douban/
    scrapy.cfg  ==> project的配置文件,通常不用改
    douban/
        __init__.py
        items.py  ==> 定義抓取的數據結構
        pipelines.py
        settings.py ==》 項目的具體配置,須要更改
        spiders/    ==》 這個是定義蜘蛛機器人的目錄
            __init__.py
            ...
2, 在item.py中定義要抓取的數據結構:定義了一個DoubanItem,屬性包括name,url, total member number, relative groups, active users。 

定義完DoubanItem後,你就能夠在實現蜘蛛機器人的代碼裏返回DoubanItem的實例,Scrapy會自動序列化並導出到JSON/XML等。 網絡

from scrapy.item import Item, Field

class DoubanItem(Item):
    # define the fields for your item here like:
    # name = Field()
    groupName = Field()
    groupURL = Field()
    totalNumber = Field()
    RelativeGroups = Field()
    ActiveUesrs = Field()

3, 定義一個最簡單的蜘蛛機器人: 抓取豆瓣小組的首頁並保存在一個文件裏。咱們在spiders目錄下新建一個蜘蛛文件:BasicGroupSpider.py,程序內容以下: 數據結構

from scrapy.spider import BaseSpider
from scrapy.item import Item
from douban.items import DoubanItem

class GroupTestSpider(BaseSpider):
	name = "Test"
	allowed_domains = ["douban.com"]
	start_urls = [
		"http://www.douban.com/group/",
	]

	def parse(self, response):
		self.log("Fetch douban homepage page: %s" % response.url)
		open("test.data", "wb").write(response.body)

能夠看到:程序擴展了BaseSpider類來建立一個自定義的蜘蛛。BaseSpider是Scrapy中自定義的最簡單蜘蛛,它沒有爬行功能,只抓取在start_urls裏面定義的網址,並調用parse方法處理每一個抓取的response。 app

而後運行在command line中執行以下命令,將運行上述蜘蛛機器人,並將log寫到test.log中。 dom

scrapy crawl Test --logfile=test.log

4, 接下來要抓取某一個豆瓣小組頁面,例如http://www.douban.com/group/WHV/, 而後解析出小組的名稱,成員總數,以及相關的友情小組和推薦小組的URL——這些信息將用於構建小組之間的鏈接。

爲此須要引入一個包HTML解析包:

from scrapy.selector import HtmlXPathSelector
從新定義 BasicGroupSpider.py以下:
from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from scrapy.item import Item
from douban.items import DoubanItem
import re

class GroupTestSpider(BaseSpider):
	name = "Test"
	allowed_domains = ["douban.com"]
	start_urls = [
		"http://www.douban.com/group/WHV/",
	]

	def __get_id_from_group_url(self, url):
		m =  re.search("^http://www.douban.com/group/([^/]+)/$", url)
		if(m):
			return m.group(1) 
		else:
			return 0

	def parse(self, response):
		
		self.log("Fetch group home page: %s" % response.url)

		hxs = HtmlXPathSelector(response)
		item = DoubanItem()

		#get group name
		item['groupName'] = hxs.select('//h1/text()').re("^\s+(.*)\s+$")[0]

		#get group id 
		item['groupURL'] = response.url
		groupid = self.__get_id_from_group_url(response.url)

		#get group members number
		members_url = "http://www.douban.com/group/%s/members" % groupid
		members_text = hxs.select('//a[contains(@href, "%s")]/text()' % members_url).re("\((\d+)\)")
		item['totalNumber'] = members_text[0]

		#get relative groups
		item['RelativeGroups'] = []
		groups = hxs.select('//div[contains(@class, "group-list-item")]')
		for group in groups:
			url = group.select('div[contains(@class, "title")]/a/@href').extract()[0]
			item['RelativeGroups'].append(url)
		#item['RelativeGroups'] = ','.join(relative_groups)
		return item
爲了解析抓取到的網頁,parse方法作了較大改動:
  • 咱們使用了HtmlXPathSelector從response中創建一個dom對象hxs
  • 爲了獲得小組名稱,使用hxs.select('//h1/text()')獲得h1標題的內容,而後用re("^\s+(.*)\s+$")過濾到標題的空格
  • 爲了獲得小組的相關小組,使用hxs.select('//div[contains(@class, "group-list-item")]')獲得一個小組列表,而後在for循環中select小組的URL,並append到item['RelativeGroups']數組中
運行以下command命令:
scrapy crawl Test --logfile=test.log -o test.json -t json

Scrapy會把解析後返回的item序列化爲json格式並保存在test.json文件中。

到此爲止完成了抓取工做的一半——蜘蛛還不能自動爬行來解析網頁,下篇博客打算講講如何讓蜘蛛在網頁間爬行,以及如何操做cookie等內容。

用Scrapy抓取豆瓣小組數據(二)http://my.oschina.net/chengye/blog/124162

相關文章
相關標籤/搜索