python简单框架实现爬取NBA球员数据

寒假期间就像爬取球员数据,一直 没有动手写。一下是代码和注释,存在一些小小的bug,就是文件写入问题,学习完写入exel后再修改。

爬虫总调度程序:

#-*-coding:UTF-8 -*- from Html_Download import HtmlDownload #从Html_Download.py文件中导入HtmlDownload类,以下相同 from Url_Manage import UrlManage from Html_Parse import HtmlParse from Output_Data import OutputData class NBASpiderMain(): #定义一个NBASpiderMain()类 def __init__(self): #个人理解对类进行初始化。关于更多__init__的理解详见:http://www.crifan.com/summary_the_meaning_of_self_and___init___in_python_and_why_need_them/ self.urls = UrlManage() #创建urls,download,parser,oupter对象。分别对应爬虫框架的 self.downloader = HtmlDownload() #url管理器,下载器,解析器,和对文件的输出 self.parser = HtmlParse() self.outputer = OutputData() def craw(self,root_url): #定义一个爬取的方法 self.urls.addUrl(root_url) #将原始URL通过urls的addUrl方法添加到待爬取的URL池中 while self.urls.hasUrl(): #urls对象调用hasUrl方法,判断URL池中是否含有待爬取的URL url = self.urls.getUrl() #如果存在待爬取的URL,通过urls的getUrl方法获取一个待爬取URL html_count = self.downloader.getHtmlCount(url) #通过调用下载器的getHtmlCount()方法去获取网页源码 playerUrls = self.parser.getPlayerUrls(html_count) #通过解析,得到第二层待爬取的URL(球员信息所在的页面)。返回一个列表 while playerUrls: #爬取后的得到的列表中的URL不为空 playerUrl = playerUrls.pop() #pop()方法,得到一个列表中元素,同时在列表中删除这个元素。(拿出来不放回去) self.urls.addPlayerUrl(playerUrl) #将以爬取的球员信息URL存储在一个列表中 HtmlPlayer = self.downloader.getHtmlCount(playerUrl) #爬取球员信息URL,得其源码 PlayerData = self.parser.getPlayerData(HtmlPlayer) #解析源码,得球员信息 self.outputer.writeData(PlayerData) #将球员信息写入文件 print(playerUrl+"数据爬取完成") if __name__ == "__main__": root_url = "http://nba.sports.sina.com.cn/players.php?dpc=1" obj_spider = NBASpiderMain() #创建一个爬取NBA数据的对象 obj_spider.craw(root_url) #调用对象的爬取方法 url管理器:

#-*-coding:UTF-8 -*-
class UrlManage(object):
	''' URL管理器,管理URL池'''
	def __init__(self):					#初始化此类
		self.new_url=set()				#创建一个new_url集合,用来存储待爬取得URL
		#self.player_url = set()
		self.old_player_url = set()		#创建一个已经爬取的球员信息URL
	def hasUrl(self):					#创建判断待爬取的列表中是否存在URL
		if self.new_url:				#如果待爬取的列表不为空	
			return True
		else:
			False
	def addUrl(self,url):				#增加待爬取的URL到列表中
		if url not in self.new_url:
			self.new_url.add(url)
		else:
			return "该url已经爬取过"
	def getUrl(self):					#获取待爬取的URL中的一个URL元素
		if self.new_url:
			return self.new_url.pop()
		else:
			return "已经没有可爬取的URL"
	def addPlayerUrl(self,url):			#增加一个已经爬取的球员信息URL到列表中
		self.old_player_url.add(url)
		return

下载器:

#-*-coding:UTF-8 -*-
import requests
class HtmlDownload(object):
	"""docstring for HtmlDownload"""
	def getHtmlCount(self,url):
		try:
			r = requests.get(url)
			r.raise_for_status()
			r.encoding = r.apparent_encoding
			return r.text
		except Exception as e :
			print(e)
			print("下载网页源码失败")
		

解析器:

#-*-coding:UTF-8-*-
import re
from bs4 import BeautifulSoup
class HtmlParse(object):
	"""docstring for HtmlParse用于解析HTML来得到球员信息的类"""
	def __init__(self):											#初始化解析器
		self.playerUrl=set()
		self.HtmlData = []

	def getPlayerUrls(self,html_count):							#解析原始页面中各个球员信息的URL,返回一个集合
		soup = BeautifulSoup(html_count,"html.parser")
		playerUrlsPart = soup.find_all('a')
		for url in playerUrlsPart:

			path = re.findall(r'a href="player\.php?(.+)">.*',str(url))
			if path:
				self.playerUrl.add("http://nba.sports.sina.com.cn/player.php"+"".join(i for i in path))
				print("http://nba.sports.sina.com.cn/player.php"+"".join(i for i in path))
			else:
				continue
		return self.playerUrl
	def getPlayerName(self,html_count):							#由于BeautifulSoup没有解析出名字,使用之前的正则表达式解析
		player_name = re.findall(r'(.+)',html_count)
		return player_name
	def getPlayerTeam(self,html_count):							#由于BeautifulSoup没有解析出球队名字,使用之前的正则表达式解析
		team_name = re.findall(r'(.+)',html_count)
		return team_name[0]										#解析出该球员每个赛季虽所在的球队名字,选取第一个就是今年现在所在的	
	def getPlayerData(self,html_count):							#通过BeautifulSoup解析球员信息。解析出为下面注释的列表内容,通过索引得到想要的信息					
		soup = BeautifulSoup(html_count,"html.parser")
		player_data = {}										#通过字典来存储球员信息的对象
		tr  = soup.find_all(bgcolor=re.compile(r'#fcac08'))		#find_all()方法加正则来寻找球员信息所在的标签。加入正则目的是过滤掉其他的内容
		for i in tr:											#返回的是列表,所以遍历
			for x in i.find_all('td'):							#对每个标签,向下寻找子标签,返回还是列表,所以遍历
				self.HtmlData.append(x.string)					#返回每个标签的String内容,并添加到一个列表中
		player_data["name"] = self.getPlayerName(html_count)
		player_data["team_name"] = self.getPlayerTeam(html_count)
		player_data["age"] = self.HtmlData[4]
		player_data["birthday"] = self.HtmlData[2]
		player_data["height"] = self.HtmlData[10]
		player_data["weight"] = self.HtmlData[12]
		player_data["veteran"] = self.HtmlData[-7]
		
		return player_data
		'''
		从网页上通过BeautifulSoup上解析出来的数据,保存在列表中
		[None, '生\u3000\u3000日', '1984-03-24', '年\u3000\u3000龄', '33岁', '出 生 地', '德克萨斯州达拉斯', '毕业学校', 'Georgi
a Tech', '身\u3000\u3000高', '\r\n\t2.11米(6英尺11英寸)\r\n\t', '体\u3000\u3000重', '\r\n\t107公斤(235磅)', '进入 NBA',
'2003年', 'NBA 球龄', '13年', '伤病情况', None, '停赛情况', None, '选秀情况', '\r\n\t2003年第1轮第4顺位被猛龙队选中']
		'''
	


	'''
	一下代码为当初分析时使用的正则,当爬取到体重身高数据时不会爬取了,改用BeautifulSoup网页解析



	def getPlayerData_2(self,html_count):
		player_data = {}
		player_data["name"] = self.getPlayerName(html_count)
		player_data["age"] = self.getPlayerAge(html_count)
		player_data["birthday"] = self.getPlayerBirthday(html_count)
		player_data["height"] = self.getPlayerHeigth(html_count)
		player_data["weight"] = self.getPlayerWeight(html_count)
		player["veteran"] = self.getPlayerVeteran(html_count)
		return player_data
	def getPlayerName(self,html_count,soup):
		player_name = re.findall(r'(.+)',html_count)
		return player_name
	def getPlayerTeam(self,html_count):
		team_name = re.findall(r'(.+)',html_count)
		return TeamName
	def getPlayerAge(self,html_count):
		player_age = re.findall(r'(.*)',html_count)[1]
		return player_age
	def getPlayerBirthday(self,html_count):
		player_birthday = re.findall(r'(.*)',r.text)[0]
		return player_birthday
	def getPlayerHeigth(self,html_count):
		p
	def getPlayerWeight(self,html_count):
		pass
	def getPlayerVeteran(self,html_count):
		pass
	'''
	

输出数据:

#-*-encoding:UTF-8  -*-
import os 
class OutputData(object):
    def __int__(self):
        self.path = r"D:\\NBAPlayerData"
    def writeData(self,player_data):
        self.path = r"D:\\NBAPlayerData"
        if os._exists(self.path):
            f = open(path+".txt","a")


            data = str(player_data["name"])+" "+str(player_data["team_name"])+" "+str(player_data["age"])+"  "+str(player_data["birthday"])+"  "+str(player_data["height"])+"  "+str(player_data["weight"])+"  "+str(player_data["veteran"])
            f.write(data)
            f.close()


以上为全部代码,欢迎指出错误。(关于函数的访问控制在此没有涉及,这是个毛病)

你可能感兴趣的:(python)