用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

相关文章
相关标签/搜索