python爬虫(15)爬取百度百科字条_精品

python爬虫(15)爬取百度百科字条——学自慕课网

写在前面的话

这段时间在学python,感觉用它爬取网络上的内容挺有意思的,然后在慕课网上看到一个爬取百度百科python字条的一个教学视频

人家讲的挺清楚的,就是没有给源码,然后自己就照着视频敲了一遍,中间遇到各种问题,不过好在还算顺利,最终程序顺利的运行起来了,

好了,话不多说,源码奉上:

 

代码目录结构:

├── baike_spider
│   ├── html_downloader.py
│   ├── html_outputer.py
│   ├── html_parser.py
│   ├── __init__.py
│   ├── spider_main.py
│   └── url_manager.py

 

主要分为几个模块:

spider_main.py:爬虫主程序

 html_downloader.py:网页下载器

html_outputer.py:内容输出器

html_parser.py:网页内容解析器

url_manager.py:url管理器

 

注意:本程序在ubuntu上完美运行,如果需要在windows 上运行的话,需要将每个文件的第一句话去掉(#!/usr/bin/python),

python版本是2.7的,需要用到几个库,如果是ubuntu就很方便了,基本上都自带了,在windows上需要自己去安装 ,主要是bs4

最终输出的文件在网页上打开的话需要自己选定编码格式为UTF-8,  如果自己在html_outputer.py中将输出格式换为gbk格式的话

 

源代码:

spider_main.py

#!/usr/bin/python
#coding:utf-8

import url_manager,html_downloader,html_parser,html_outputer

class SpiderMain(object):
	
	#构造函数,初始化各类管理器,解析器,下载器等
	def __init__(self):
		self.urls = url_manager.UrlManager()
		self.downloader = html_downloader.HtmlDownloader()
		self.parser = html_parser.HtmlParser()
		self.outputer = html_outputer.HtmlOutputer()
	
	def craw(self,root_url):
		#将入口url添加进url管理器,url管理器中有一个待爬取的url,就可以启动循环了
		count = 1 #用于计数,计算当前爬取的是第几个url
		self.urls.add_new_url(root_url)
		
		while self.urls.has_new_url():
			try:#加入异常处理,有的网页打开没有数据

				new_url = self.urls.get_new_url()#从url管理器获取一个url
			
				print 'crawl %d: %s' % (count,new_url)
				html_cont  = self.downloader.download(new_url)#获取完url,就要去下载它
				new_urls,new_data = self.parser.parse(new_url,html_cont)#下载url,就会得到新的url列表,和新的数据,那么我们就要去处理它
				self.urls.add_new_urls(new_urls)#将新的urls 添加到url管理器中
				self.outputer.collect_data(new_data)
				#将新的数据收集起来
				
				if count == 1000:
					break
			
				count = count +1
			except:
				print 'craw_fail'
		self.outputer.output_html()

if __name__ == "__main__":

	root_url = "http://baike.baidu.com/view/21087.htm"
	obj_spider = SpiderMain()
	obj_spider.craw(root_url)

html_downloader.py

#!/usr/bin/python
#coding:utf-8

import urllib

class HtmlDownloader(object):
	
	def download(self,url):
		if url is None:
			return None
		response = urllib.urlopen(url)
		
		if response.getcode()!=200 :
			return None
			  
		return response.read()

 

url_manager.py


 
#!/usr/bin/python
#coding:utf-8

class UrlManager(object):
	
	def __init__(self):
		self.new_urls = set()#用set()方法作为存储单元,可以自动去重
		self.old_urls = set()
	
	def add_new_url(self,url):
		if url is None:#新进来的url要对其做检查,是空就不管,然后还得不在new和old两个列表中才行
			return
		if url not in self.new_urls and url not in self.old_urls:
			self.new_urls.add(url)
		
	def add_new_urls(self,urls):#新来的urls不能为空
		if urls is None or len(urls) ==  0:
			return
		for url in urls:
			self.add_new_url(url)

	def has_new_url(self):#判断是否有新的urls,如果new_urls的列表长度不为0就代表有新的
		return len(self.new_urls) != 0
		
	def get_new_url(self):
		new_url = self.new_urls.pop()#从urls管理器中取出一个url
		self.old_urls.add(new_url)#取出之后,就要将其放入old urls存储空间中
		return new_url

html_parser.py

#!/usr/bin/python
#coding:utf-8

from bs4 import BeautifulSoup
import re
import urlparse

class HtmlParser(object):
	
	def _get_new_urls(self,page_url,soup):
		new_urls = set()
		#/view/123.htm

		links = soup.find_all('a',href =re.compile(r"/view/\d+\.htm"))

		for link in links:
			new_url = link['href']
			new_full_url = urlparse.urljoin(page_url,new_url)#网址拼接函数,第二个按照第一个的形式拼接
			new_urls.add(new_full_url)
		return new_urls
		
	def _get_new_data(self,page_url,soup):
		res_data = {}
		
		res_data['url'] = page_url
		#

Python

title_node = soup.find(‘dd’,class_=”lemmaWgt-lemmaTitle-title”).find(“h1”) res_data[‘title’] = title_node.get_text() #

summary_node =soup.find(‘div’,class_=”lemma-summary”) res_data[‘summary’] = summary_node.get_text() return res_data def parse(self,page_url,html_cont): if page_url is None or html_cont is None: return soup = BeautifulSoup(html_cont,’html.parser’,from_encoding = ‘utf-8’) new_urls = self._get_new_urls(page_url,soup) new_data = self._get_new_data(page_url,soup) return new_urls,new_data

html_outputer.py

#!/usr/bin/python
#coding:utf-8

class HtmlOutputer(object):
	
	def __init__(self):
		self.datas = [ ]
			
	def collect_data(self,data):
		if data is None:
			return None
		print data['url']
		print data['title'].encode('utf-8')
		print data['summary'].encode('utf-8')
		self.datas.append(data)
		
	def output_html(self):
		fout = open('output.html','w')
		
		fout.write("

“) fout.write(“

“) fout.write(“”) #ascii for data in self.datas: fout.write(“”) fout.write(“” % data[‘url’]) fout.write(“” ) fout.write(“” % data[‘title’].encode(‘utf-8’)) fout.write(“” % data[‘title’].encode(‘gbk’))#这种格式就直接是中文了 fout.write(“” ) fout.write(“” % data[‘summary’].encode(‘utf-8’)) fout.write(“”) fout.write(“

%s\t%s%s\t%s

“) fout.write(“

“) fout.write(“”) fout.close()

__init_.py(这个文件中什么也没有)

 

代码运行:

ubuntu下执行:python spider_main.py

或者给spider_main.py加上可执行权限(chmod 777 spider_main.py) 然后执行 ./spider_main.py

 

 

运行结果如下:

crawl 1: http://baike.baidu.com/view/21087.htm
http://baike.baidu.com/view/21087.htm
Python

Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum于1989年发明,第一个公开发行版发行于1991年。Python是纯粹的自由软件, 源代码和解释器CPython遵循 GPL(GNU General Public License)协议[1] 
。Python语法简洁清晰,特色之一是强制用空白符(white space)作为语句缩进。Python具有丰富和强大的库。它常被昵称为胶水语言,能够把用其他语言制作的各种模块(尤其是C/C++)很轻松地联结在一起。常见的一种应用情形是,使用Python快速生成程序的原型(有时甚至是程序的最终界面),然后对其中[2] 
有特别要求的部分,用更合适的语言改写,比如3D游戏中的图形渲染模块,性能要求特别高,就可以用C/C++重写,而后封装为Python可以调用的扩展类库。需要注意的是在您使用扩展类库时可能需要考虑平台问题,某些可能不提供跨平台的实现。

crawl 2: http://baike.baidu.com/view/16068.htm
http://baike.baidu.com/view/16068.htm
api

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

crawl 3: http://baike.baidu.com/view/53557.htm
http://baike.baidu.com/view/53557.htm
系统资源

当应用程序在Windows中运行时,Windows必须实时"跟踪"该应用程序的运行,并保留与之相关的许多信息,如光标、窗口的状况等,这些信息由Windows保留在一种叫堆的内存块中,堆的英文为Heap。简单地说,堆是采用特殊机制管理的内存块。由Windows的一个系统内核User.exe管理的堆叫作User资源堆(User Resource Heap),由另一个系统内核Gdi.exe管理的堆叫作GDI资源堆(Graphical Device Interface Resource Heap),User资源堆和GDI资源堆合称为系统资源堆(System Resource Heap),习惯上就把它们叫作系统资源(System Resource)。

crawl 4: http://baike.baidu.com/view/10812277.htm
http://baike.baidu.com/view/10812277.htm
百度百科:多义词

百度百科里,当同一个词条名可指代含义概念不同的事物时,这个词条称为多义词。如词条“苹果”,既可以代表一种水果,也可以指代苹果公司,因此“苹果”是一个多义词。

crawl 5: http://baike.baidu.com/view/32571.htm
http://baike.baidu.com/view/32571.htm
数据缓存


crawl 6: http://baike.baidu.com/view/757238.htm
http://baike.baidu.com/view/757238.htm
多任务

......

 

输出文件在网页上打开如下显示:

http://baike.baidu.com/view/21087.htm Python Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum于1989年发明,第一个公开发行版发行于1991年。Python是纯粹的自由软件, 源代码和解释器CPython遵循 GPL(GNU General Public License)协议[1]  。Python语法简洁清晰,特色之一是强制用空白符(white space)作为语句缩进。Python具有丰富和强大的库。它常被昵称为胶水语言,能够把用其他语言制作的各种模块(尤其是C/C++)很轻松地联结在一起。常见的一种应用情形是,使用Python快速生成程序的原型(有时甚至是程序的最终界面),然后对其中[2]  有特别要求的部分,用更合适的语言改写,比如3D游戏中的图形渲染模块,性能要求特别高,就可以用C/C++重写,而后封装为Python可以调用的扩展类库。需要注意的是在您使用扩展类库时可能需要考虑平台问题,某些可能不提供跨平台的实现。
http://baike.baidu.com/view/16068.htm api API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
http://baike.baidu.com/view/53557.htm 系统资源 当应用程序在Windows中运行时,Windows必须实时”跟踪”该应用程序的运行,并保留与之相关的许多信息,如光标、窗口的状况等,这些信息由Windows保留在一种叫堆的内存块中,堆的英文为Heap。简单地说,堆是采用特殊机制管理的内存块。由Windows的一个系统内核User.exe管理的堆叫作User资源堆(User Resource Heap),由另一个系统内核Gdi.exe管理的堆叫作GDI资源堆(Graphical Device Interface Resource Heap),User资源堆和GDI资源堆合称为系统资源堆(System Resource Heap),习惯上就把它们叫作系统资源(System Resource)。
http://baike.baidu.com/view/10812277.htm 百度百科:多义词 百度百科里,当同一个词条名可指代含义概念不同的事物时,这个词条称为多义词。如词条“苹果”,既可以代表一种水果,也可以指代苹果公司,因此“苹果”是一个多义词。
http://baike.baidu.com/view/32571.htm 数据缓存  
http://baike.baidu.com/view/757238.htm 多任务 多任务处理是指用户可以在同一时间内运行多个应用程序,每个应用程序被称作一个任务.Linux、windows就是支持多任务的操作系统,比起单任务系统它的功能增强了许多。当多任务操作系统使用某种任务调度策略允许两个或更多进程并发共享一个处理器时,事实上处理器在某一时刻只会给一件任务提供服务。因为任务调度机制保证不同任务之间的切换速度十分迅速,因此给人多个任务同时运行的错觉。多任务系统中有3个功能单位:任务、进程和线程。

源码下载地址;http://download.csdn.net/detail/qiqiyingse/9565030

 

代码更新:

本文写于2015年左右,此次更新时间为2018.11.2

百度百科的词条发生了一些变化(之前百度词条的地址是类似于http://baike.baidu.com/view/21087.htm

现在变为https://baike.baidu.com/item/python ,也就是说之前找的关键字是 view/数字.htm, 现在找 item),

之前的代码需要做出一点小小的改动才能继续完整的运行,新的代码如下

python2版本:

核心修改点 html_parser.py:

links = soup.find_all('a',href =re.compile(r"/item/"))

全部代码如下:

spider_main.py

# -*- coding: utf-8 -*-
# @Date     : 2018-11-02 11:22:44
# @Author   : Jimy_Fengqi (jmps515@163.com)
# @Link     : https://blog.csdn.net/qiqiyingse
# @Version  : V1.0

from bs4 import BeautifulSoup
import re
import urlparse
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
class HtmlParser(object):
	
	def _get_new_urls(self,page_url,soup):
		new_urls = set()
		#/view/123.htm

		links = soup.find_all('a',href =re.compile(r"/item/"))

		for link in links:
			new_url = link['href']
			new_full_url = urlparse.urljoin(page_url,new_url)#网址拼接函数,第二个按照第一个的形式拼接
			#print (new_full_url)
			new_urls.add(new_full_url)
		return new_urls
		
	def _get_new_data(self,page_url,soup):
		res_data = {}
		
		res_data['url'] = page_url
		#<dd class="lemmaWgt-lemmaTitle-title"><h1>Python</h1>
		title_node = soup.find('dd',class_="lemmaWgt-lemmaTitle-title").find("h1")
		if title_node:
			res_data['title'] = title_node.get_text().decode('utf-8')
		else:
			res_data['title']='null'
		
		#<div class="lemma-summary" label-module="lemmaSummary">
		summary_node =soup.find('div',class_="lemma-summary")
		if summary_node:
			res_data['summary'] = summary_node.get_text().decode('utf-8')
		else:
			res_data['summary']='null'
		return res_data
	
	
	def parse(self,page_url,html_cont):
		if page_url is None or html_cont is None:
			return

		soup = BeautifulSoup(html_cont,'html.parser',from_encoding = 'utf-8')

		new_urls  = self._get_new_urls(page_url,soup)
		new_data = self._get_new_data(page_url,soup)
		return new_urls,new_data

html_downloader.py

# -*- coding: utf-8 -*-
# @Date     : 2018-11-02 11:22:44
# @Author   : Jimy_Fengqi (jmps515@163.com)
# @Link     : https://blog.csdn.net/qiqiyingse
# @Version  : V1.0

import urllib

class HtmlDownloader(object):
	
	def download(self,url):
		if url is None:
			return None
		response = urllib.urlopen(url)
		try:
			if response.getcode()!=200 :
				return None
			return response.read().decode('utf-8')
		except:
			return None
		

html_outputer.py

# -*- coding: utf-8 -*-
# @Date     : 2018-11-02 11:22:44
# @Author   : Jimy_Fengqi (jmps515@163.com)
# @Link     : https://blog.csdn.net/qiqiyingse
# @Version  : V1.0
import sys
reload(sys)
sys.setdefaultencoding('utf-8')


class HtmlOutputer(object):
	
	def __init__(self):
		self.datas = [ ]
			
	def collect_data(self,data):
		if data is None:
			return None
		#print (data)
		print data['url']
		print data['title']

		#print data['summary']
		self.datas.append(data)

		
	def output_html(self):
		fout = open('output.html','w+')
		
		fout.write("<html>")
		fout.write("<body>")
		fout.write("<table>")
		
		#ascii
		for data in self.datas:
			fout.write("<tr>")
			fout.write("<td>%s</td>" % data['url'])
			fout.write("<td>\t</td>" )
			fout.write("<td>%s</td>" % data['title'].encode('utf-8'))
			#fout.write("<td>%s</td>" % data['title'].encode('gbk'))#这种格式就直接是中文了
			fout.write("<td>\t</td>" )
			fout.write("<td>%s</td>" % data['summary'].encode('utf-8'))
			fout.write("</tr>")
		
		fout.write("</table>")
		fout.write("</body>")
		fout.write("</html>")
		fout.close()
		

html_parser.py

# -*- coding: utf-8 -*-
# @Date     : 2018-11-02 11:22:44
# @Author   : Jimy_Fengqi (jmps515@163.com)
# @Link     : https://blog.csdn.net/qiqiyingse
# @Version  : V1.0

from bs4 import BeautifulSoup
import re
import urlparse
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
class HtmlParser(object):
	
	def _get_new_urls(self,page_url,soup):
		new_urls = set()
		#/view/123.htm

		links = soup.find_all('a',href =re.compile(r"/item/"))

		for link in links:
			new_url = link['href']
			new_full_url = urlparse.urljoin(page_url,new_url)#网址拼接函数,第二个按照第一个的形式拼接
			#print (new_full_url)
			new_urls.add(new_full_url)
		return new_urls
		
	def _get_new_data(self,page_url,soup):
		res_data = {}
		
		res_data['url'] = page_url
		#<dd class="lemmaWgt-lemmaTitle-title"><h1>Python</h1>
		title_node = soup.find('dd',class_="lemmaWgt-lemmaTitle-title").find("h1")
		if title_node:
			res_data['title'] = title_node.get_text().decode('utf-8')
		else:
			res_data['title']='null'
		
		#<div class="lemma-summary" label-module="lemmaSummary">
		summary_node =soup.find('div',class_="lemma-summary")
		if summary_node:
			res_data['summary'] = summary_node.get_text().decode('utf-8')
		else:
			res_data['summary']='null'
		return res_data
	
	
	def parse(self,page_url,html_cont):
		if page_url is None or html_cont is None:
			return

		soup = BeautifulSoup(html_cont,'html.parser',from_encoding = 'utf-8')

		new_urls  = self._get_new_urls(page_url,soup)
		new_data = self._get_new_data(page_url,soup)
		return new_urls,new_data

url_manager.py

# -*- coding: utf-8 -*-
# @Date     : 2018-11-02 11:22:44
# @Author   : Jimy_Fengqi (jmps515@163.com)
# @Link     : https://blog.csdn.net/qiqiyingse
# @Version  : V1.0

class UrlManager(object):
	
	def __init__(self):
		self.new_urls = set()#用set()方法作为存储单元,可以自动去重
		self.old_urls = set()
	
	def add_new_url(self,url):
		if url is None:#新进来的url要对其做检查,是空就不管,然后还得不在new和old两个列表中才行
			return
		if url not in self.new_urls and url not in self.old_urls:
			self.new_urls.add(url)
		
	def add_new_urls(self,urls):#新来的urls不能为空
		if urls is None or len(urls) ==  0:
			return
		for url in urls:
			self.add_new_url(url)

	def has_new_url(self):#判断是否有新的urls,如果new_urls的列表长度不为0就代表有新的
		print('调度器中还有 [%d] 个urls' % (len(self.new_urls)))
		return len(self.new_urls) != 0
		
	def get_new_url(self):
		new_url = self.new_urls.pop()#从urls管理器中取出一个url
		self.old_urls.add(new_url)#取出之后,就要将其放入old urls存储空间中
		return new_url

 

声明:本文为博主原创,代码为慕课网上所学,转载请注明出处——-qiqiyingse奉上

    原文作者:python爬虫
    原文地址: https://blog.csdn.net/qiqiyingse/article/details/51798833
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞