python实现简单爬虫(二)---- 使用urllib等python模块
2014-07-22 02:55 凝月流风 阅读(357) 评论(1) 编辑 收藏 举报之前使用scrapy实现了一个超级简单的爬虫工具,用于抓取豆瓣上面所有的编程书籍信息(由于不需要爬取整个页面的所以链接,所以不需要用到BFS or DFS,只实现顺序抓取下一页)
这次使用的是python自带的urllib 和urllib2等python模块实现,同样以豆瓣上面的爱情电影信息作为爬取对象,方法与过程其实如出一辙,同样是对每一个页面发出请求后获取响应得到的网页源码,再使用正则表达式去匹配获得所需信息,然后获取下一页的链接继续爬取。
爬取页面:
网页源码:
title and link:
desc:
确定要要抓取的页面和信息后,就可以开始写代码啦~用一个类来执行工作,最后将爬取信息存放到movie.json 文件中,代码如下:
# -*- coding:utf-8 -*- import urllib import urllib2 import re import json class FilmSpider: def __init__(self, init_url_): self.start_url = init_url_ self.contain = [] self.curPage = 1 def Parse(self): nexturl = self.start_url while nexturl != None: nexturl = self.parsePage(nexturl) self.curPage += 1 f = open('movie2.json', 'a') # JsonLinesItemExporter """ for each_item in self.contain: tar = json.dumps(each_item, ensure_ascii=False) f.write(tar+'\n') """ # JsonItemExporter first_item = True f.write('[') for each_item in self.contain: if first_item: first_item = False else: f.write(',\n') tar = json.dumps(each_item, ensure_ascii=False) f.write(tar) f.write(']') f.close() def parsePage(self, cururl): print('sola is scrawling the %d page: '%self.curPage + cururl) response = urllib2.urlopen(cururl) body = response.read() #返回所有在<tr class="item"></tr>中的字符串的list myItems = re.findall('<tr class="item">(.*?)</tr>', body, re.S) for item in myItems: # 返回所有title 和link组成的tuple所组成的list, 其实list中只有一个tuple info = re.findall('<a.*?class="nbg".*?href="(.*?)".*?title="(.*?)">', item, re.S) # 返回<p>内的描述所构成的list, 同理只有一个元素 desc = re.findall('<p.*?class="pl">(.*?)</p>', item, re.S) #newItem = Item(info[0][0], info[0][1], desc[0]) newItem = {} newItem['link'] = info[0][0] newItem['title'] = info[0][1] newItem['desc'] = desc[0] self.contain.append(newItem) print newItem['title'] print newItem['link'] print newItem['desc'] print ('\n\n------------------------------------------------------------------------------------------------\n\n') Next = re.findall('<span.*?class="next">.*?<link.*?rel="next".*?href="(.*?)"/>', body, re.S) if Next: return Next[0] return None #-------------------------Main-------------------- #program: spider for Love in Douban #author : Patrick #------------------------------------------------- print('-----------------Start crawl----------------------') initurl = 'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=0&type=T' solaSpider = FilmSpider(initurl) solaSpider.Parse() print('-----------------End crawl------------------------')
代码中关于json文件的存储由两种方式,对应于scrapy框架中的两种存储方式(JsonLinesItemExporter 和 JsonItemExporter 都继承于BaseItemExporter):
1. JsonLinesItemExporter: 也就是将每一个item转换成json格式后写入,对应与Scrapy中的代码如下:
2. JsonItemExporter: 将所有转换成json格式的item再统一放进一个list里面,对应scrapy代码如下:
好啦,得到的movie.json 就是酱:
下面是用多线程版本进行爬取,使用了5个线程,速度比上面单线程快了很多
# -*- coding:utf-8 -*- import urllib import urllib2 import re import json import thread import threading class FilmSpider: def __init__(self, init_url_): self.start_url = init_url_ self.contain = [] self.curPage = 0 def Parse(self): i = 0 th = [] while i < 5: pid = threading.Thread(target=self.parsePage, args=(self.start_url[i],i)) pid.start() th.append(pid) i = i+1 i = 0 while i < 5: th[i].join() i = i+1 f = open('movie2.json', 'a') # JsonLinesItemExporter """ for each_item in self.contain: tar = json.dumps(each_item, ensure_ascii=False) f.write(tar+'\n') """ # JsonItemExporter first_item = True f.write('[') for each_item in self.contain: if first_item: first_item = False else: f.write(',\n') tar = json.dumps(each_item, ensure_ascii=False) f.write(tar) f.write(']') f.close() def parsePage(self, cururl, ID): print('sola is scrawling the %d page: '%ID + cururl) response = urllib2.urlopen(cururl) body = response.read() #返回所有在<tr class="item"></tr>中的字符串的list myItems = re.findall('<tr class="item">(.*?)</tr>', body, re.S) for item in myItems: # 返回所有title 和link组成的tuple所组成的list, 其实list中只有一个tuple info = re.findall('<a.*?class="nbg".*?href="(.*?)".*?title="(.*?)">', item, re.S) # 返回<p>内的描述所构成的list, 同理只有一个元素 desc = re.findall('<p.*?class="pl">(.*?)</p>', item, re.S) #newItem = Item(info[0][0], info[0][1], desc[0]) newItem = {} newItem['link'] = info[0][0] newItem['title'] = info[0][1] newItem['desc'] = desc[0] self.contain.append(newItem) """ print (newItem['title']) print (newItem['link']) print (newItem['desc']) print ('\n\n------------------------------------------------------------------------------------------------\n\n') """ Next = 'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=' Next += str((ID+5)*20) + '&type=T' Next = Next.strip() if ID+5 > 274: thread.exit() self.parsePage(Next, ID+5) #-------------------------Main-------------------- #program: spider for Love in Douban #author : Patrick #------------------------------------------------- print('-----------------Start crawl----------------------') initurl = ['http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=0&type=T', 'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=20&type=T', 'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=40&type=T', 'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=60&type=T', 'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=80&type=T' ] solaSpider = FilmSpider(initurl) solaSpider.Parse() print('-----------------End crawl------------------------')