示例#1
0
文件: Koala.py 项目: figot/pykoala
	def remove_next_entry(self, nextEntries):
		'''
		删除数据库中对应的NextEntry

		@param nextEntries: NextEntry表
		@type nextEntries: pythpn序列类型

		@return: 无
		'''
		for entryURL in nextEntries:
			self.collNextEntry.remove({KoalaStatus.DOC_FIELD_HASH: Common.hash(entryURL)}, safe = True)
示例#2
0
文件: Koala.py 项目: figot/pykoala
	def __init__(self, webSiteURL, entryFilter = None, yieldFilter = None, identifier = None, enableStatusSupport = False):
		'''
		@param webSiteURL: 网站url地址
		@type webSiteURL: 字符串
		@param entryFilter: 入口过滤器,指定了爬虫可以进入哪些url。定义为字典,详情如下:
							['Type']
								'allow'	允许模式,只要满足过滤项目表中的任意一项即允许
								'deny'	排除模式,只要满足过滤项目表中的任意一项即排除
							['List']
								过滤项目列表,每一项均为正则表达式,字符串
		@type entryFilter: 字典
		@param yieldFilter: 生成过滤器,指定了爬虫要生成哪些url。定义为字典,详情如下:
							['Type']
								'allow'	允许模式,只要满足过滤项目表中的任意一项即允许
								'deny'	排除模式,只要满足过滤项目表中的任意一项即排除
							['List']
								过滤项目列表,每一项均为正则表达式,字符串
		@type yieldFilter: 字典
		@param identifier: 爬虫的id,用来标识爬虫
		@type identifier: 字符串
		@param enableStatusSupport: 是否启用状态支持,默认不启用
		@type enableStatusSupport: 布尔值
		'''
		if not webSiteURL:
			raise ValueError('You must specified "webSiteURL" parameter in constructor')

		webSiteURL = Common.to_unicode(webSiteURL)

		# 如果url没有协议前缀,则使用默认协议前缀
		webSiteURL = ensure_url_default_scheme(webSiteURL)

		self.domain 		= get_domain(webSiteURL)
		self.webSiteURL 	= webSiteURL
		self.entryFilter 	= entryFilter
		self.yieldFilter 	= yieldFilter

		# 如果没有指定id,则生成uuid
		if not identifier:
			self.identifier = str(uuid.uuid1())
		else:
			self.identifier = identifier

		# 是否启用状态支持的标记
		if not enableStatusSupport:
			self.koalaStatus = None
		else:
			self.koalaStatus = KoalaStatus(Common.hash(self.webSiteURL))

		# 记录访问过的页面
		self.visitedEntriesHash = set()
示例#3
0
文件: Koala.py 项目: figot/pykoala
	def add_next_entry(self, nextEntries):
		'''
		添加NextEntry到数据库,忽略重复项

		@param nextEntries: NextEntry表
		@type nextEntries: pythpn序列类型

		@return: 无
		'''
		for entryURL in nextEntries:
			doc = dict()
			doc[KoalaStatus.DOC_FIELD_HASH] 	= Common.hash(entryURL)
			doc[KoalaStatus.DOC_FIELD_URL] 		= entryURL
			try:
				self.collNextEntry.insert(doc, safe = True)
			except pymongo.errors.DuplicateKeyError as e:
				Common.write_stderr(repr(e))
示例#4
0
文件: Koala.py 项目: figot/pykoala
	def __crawl_proc(self, entryURL, maxDepth):
		'''
		爬行的执行过程

		@param entryURL: 爬虫的入口url
		@type entryURL: 字符串
		@param maxDepth: 最大抓取深度
		@type maxDepth: 整数

		@return: 满足过滤条件的url
		@rtype: 字符串
		'''
		# 如果达到最大深度则返回
		if maxDepth <= 0:
			return

		# 解析出页面中所有的链接
		try:
			source = get_url_html(entryURL)
			soup = BeautifulSoup(source, Config.DEFAULT_HTML_PARSER)
		except Exception as e:
			Common.write_stderr(repr(e))
			return
		links = list()
		for a in soup.find_all('a'):
			try:
				links.append(a['href'].encode(Common.UTF8_CHARSET_NAME))
			except KeyError as e:
				Common.write_stderr(repr(e))
		links = [Common.to_unicode(l) for l in links]

		# 生成符合规则的链接,并记录符合规则的子页面
		nextEntries = list()
		for link in links:
			url = urlparse.urljoin(entryURL, link)
			if self.__global_filter(entryURL, url):
				if self.__yield_filter(url):
					yield url
				if self.__entry_filter(url):
					nextEntries.append(url)

		# 执行到此处代表一个(子)页面(EntryURL)处理完成

		# 需要记录到已处理页面集合中。处于性能考虑,记录url的hash值而非url本身
		self.visitedEntriesHash.add(Common.hash(entryURL))

		# 如果启用状态支持,则同步删除数据库中对应的NextEntry数据(如果有的话)
		if self.koalaStatus:
			self.koalaStatus.remove_next_entry([entryURL])

		# 如果即将达到最大深度,处于性能考虑,不再进入子页面
		if maxDepth - 1 <= 0:
			return
		else:
			# 准备进入子页面之前,同步更新状态
			if self.koalaStatus:
				self.koalaStatus.add_next_entry(nextEntries)

			# 广度优先抓取
			for nextEntryURL in nextEntries:
				if Common.hash(nextEntryURL) not in self.visitedEntriesHash:
					for i in self.__crawl_proc(nextEntryURL, maxDepth - 1):
						yield i