用Scrapy抓取豆瓣小组数据(一)

最近在coursera.org(在线学习平台)上学SNA(Social Network Analysis,社交网络分析)。有兴趣的同学可以去看一眼:https://class.coursera.org/sna-002/,课程讲的很有意思,等回头我上完全部课程打算再写下详细总结和思考。

为什么要抓取豆瓣小组数据?

  课程要做一个带编程的final project,大概内容就是自己找一个网络数据集,然后按照课程中提供的方法进行分析。其实最难的部分是找数据,两种方法:自己抓,或者是找现成的。对于后者,国内有个叫数据堂的数据分享网站做的不错,上面有豆瓣,淘宝,微博等各种数据,不过有些数据需要收费;国外有个叫Konect的网站专注于复杂网络数据。

  看了一圈现成的数据都不太满意,决定自己抓取了。目标锁定豆瓣小组,打算分析小组之间的互相联系。

如何用Scrapy抓取网页?

还不太了解Scrapy的同学直接看这里http://www.oschina.net/p/scrapy,这边就不赘述基本功能和安装方式。

1,先建立一个scrapy项目,项目名称doubanscrapy startproject douban

1 scrapy startproject douban

会生成一个项目目录,内部结构大概如下:

01 douban/
02     scrapy.cfg  ==> project的配置文件,一般不用改
03     douban/
04         __init__.py
05         items.py  ==> 定义抓取的数据结构
06         pipelines.py
07         settings.py ==》 项目的具体配置,需要更改
08         spiders/    ==》 这个是定义蜘蛛机器人的目录
09             __init__.py
10             ...
2, 在item.py中定义要抓取的数据结构:定义了一个DoubanItem,属性包括name,url, total member number, relative groups, active users。 

定义完DoubanItem后,你就可以在实现蜘蛛机器人的代码里返回DoubanItem的实例,Scrapy会自动序列化并导出到JSON/XML等。

01 from scrapy.item import Item, Field
02  
03 class DoubanItem(Item):
04     # define the fields for your item here like:
05     # name = Field()
06     groupName = Field()
07     groupURL = Field()
08     totalNumber = Field()
09     RelativeGroups = Field()
10     ActiveUesrs = Field()

3, 定义一个最简单的蜘蛛机器人: 抓取豆瓣小组的首页并保存在一个文件里。我们在spiders目录下新建一个蜘蛛文件:BasicGroupSpider.py,程序内容如下:

01 from scrapy.spider import BaseSpider
02 from scrapy.item import Item
03 from douban.items import DoubanItem
04  
05 class GroupTestSpider(BaseSpider):
06     name = "Test"
07     allowed_domains = ["douban.com"]
08     start_urls = [
09         "http://www.douban.com/group/",
10     ]
11  
12     def parse(self, response):
13         self.log("Fetch douban homepage page: %s" % response.url)
14         open("test.data""wb").write(response.body)
15         

可以看到:程序扩展了BaseSpider类来创建一个自定义的蜘蛛。BaseSpider是Scrapy中自定义的最简单蜘蛛,它没有爬行功能,只抓取在start_urls里面定义的网址,并调用parse方法处理每个抓取的response。

然后运行在command line中执行如下命令,将运行上述蜘蛛机器人,并将log写到test.log中。

1 scrapy crawl Test --logfile=test.log

4, 接下来要抓取某一个豆瓣小组页面,例如http://www.douban.com/group/WHV/, 然后解析出小组的名称,成员总数,以及相关的友情小组和推荐小组的URL——这些信息将用于构建小组之间的连接。

为此需要引入一个包HTML解析包:

1 from scrapy.selector import HtmlXPathSelector
重新定义  BasicGroupSpider.py 如下:
01 from scrapy.spider import BaseSpider
02 from scrapy.selector import HtmlXPathSelector
03 from scrapy.item import Item
04 from douban.items import DoubanItem
05 import re
06  
07 class GroupTestSpider(BaseSpider):
08     name = "Test"
09     allowed_domains = ["douban.com"]
10     start_urls = [
11         "http://www.douban.com/group/WHV/",
12     ]
13  
14     def __get_id_from_group_url(self, url):
15         =  re.search("^http://www.douban.com/group/([^/]+)/$", url)
16         if(m):
17             return m.group(1)
18         else:
19             return 0
20  
21     def parse(self, response):
22          
23         self.log("Fetch group home page: %s" % response.url)
24  
25         hxs = HtmlXPathSelector(response)
26         item = DoubanItem()
27  
28         #get group name
29         item['groupName'= hxs.select('//h1/text()').re("^\s+(.*)\s+$")[0]
30  
31         #get group id
32         item['groupURL'= response.url
33         groupid = self.__get_id_from_group_url(response.url)
34  
35         #get group members number
36         members_url = "http://www.douban.com/group/%s/members" % groupid
37         members_text = hxs.select('//a[contains(@href, "%s")]/text()' % members_url).re("\((\d+)\)")
38         item['totalNumber'= members_text[0]
39  
40         #get relative groups
41         item['RelativeGroups'= []
42         groups = hxs.select('//div[contains(@class, "group-list-item")]')
43         for group in groups:
44             url = group.select('div[contains(@class, "title")]/a/@href').extract()[0]
45             item['RelativeGroups'].append(url)
46         #item['RelativeGroups'] = ','.join(relative_groups)
47         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命令:
1 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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值