使用python实现简单的百度百科词条爬虫
2016-01-01 23:20
639 查看
一、爬虫
有效、批量下载数据的工具
二、简单爬虫架构
1.爬虫调度程序
2.url管理器
3.网页下载器
4.网页解析器
5.文件输出器
三、实现
此处将用python 2.7.9实现一个简单的爬虫,从python词条开始爬取1000条百度百科中的词条。
1.python urllib2下载网页的三种方式
(1)直接请求
import urllib2
#直接请求
response = urllib2.urlopen("www.baidu.com")
#获取状态码, 如果是200表是获取成功
print response.getcode()
#读取内容
content = response.read()
(2)添加data、http header
import urllib2
#创建request对象
request = urllib2.Request(url)
#添加数据
request.add_data("a", "1");
#添加http的header #伪装成火狐浏览器
request.add_header("User-agent", "Mozilla/5.0")
#发送请求, 获取结果
response = urllib2.urlopen(request)
(3)添加特殊情景的处理器
用户登录访问: HTTPCookieProcessor
代理访问: ProxyHandler
HTTPS协议: HTTPSHandler
自动跳转关系: HTTPRedirectHandler
#以上handler传送给urllib2
opener = urllib2.build_opener(handler)
#urllib2模块具有场景处理能力
urllib2.install_opener(opener)
#
urllib2.urlopen(url)
urllib2.urlopen(request)
<code>
#e.g. cookie增强版
import urllib2, cookielib
#创建cookie容器
cj = cookielib.CookieJar()
#创建1个opener
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
#给urllib2安装opener
urllib2.install_opener(opener)
#使用带有cookie的urllib2访问网页
response = urllib2.urlopen("www.baidu.com")
</code>
2.python的网页解析器
1)模糊匹配
正则表达式
2)结构化解析
html.parser
Beautiful Soup
lxml
3.Beautiful Soup语法
1)创建BeautifulSoup对象
#code
from bs4 import BeautifulSoup
#根据HTML网页字符串创建BeautifulSoup对象
soup = BeautifulSoup(
html_doc,
#HTML文档字符串
"html.parser",
#HTML解析器
from_encoding="utf-8"
#HTML文档编码格式
)
2)搜索节点(find_all, find)
# 方法: find_all(name, attrs, string) string参数为标签内容
#查找所有标签为a的节点
soup.find_all("a")
#查找所有标签为a,链接符合/view/123.html形式的节点
soup.find_all("a", href="/view/123.html")
soup.find_all("a", href=re.cpmpile(r'/view/\d+\.html') )
#正则形式
#查找所有标签为div, class为abc, 文字为python的节点
soup.find_all("div", class_="abc", string="python")
#class为python保留字,所以加下划线。
3)访问节点信息
#得到节点: <a href="1.html">python</a>
#获取查找到的节点的标签名称
node.name
#获取查找到的a节点的href属性
node["href"]
#获取查找的a节点的链接文字
node.get_text()
4)BeautifulSoup测试实例
<code>
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc, "html.parser", from_encoding="utf-8")
print "获取所有的链接"
links = soup.find_all("a")
for link in links:
print link.name, link["href"], link.get_text()
print "获取lacie的链接"
</code>
四、简单实例
1.调度程序 spider_main.py
<code>
#encoding:utf-8
'''
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
from com.baidu.baike_spider 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()
print "init SpiderMain success"
def craw(self, root_url): #开始爬取
#记录当前在爬取的url序号
count = 1
#初始化urls队列
self.urls.add_new_url(root_url)
#爬取循环
while self.urls.has_new_url():
#异常处理
try:
#获取新的url
new_url = self.urls.get_new_url()
print "crawing #%d : %s" %(count, new_url)
html_content = self.downloader.download(new_url)
new_urls, new_data = self.parser.parse(new_url, html_content)
self.urls.add_new_urls(new_urls)
self.outputer.collect_data(new_data)
#只爬取1000个页面
if count == 1000:
break
#计数器加1
count = count + 1
except:
print "craw failed"
self.outputer.output_html()
print "this job is done!"
if __name__ == "__main__":
root_url = "http://baike.baidu.com/view/21087.htm"
obj_spider = SpiderMain()
obj_spider.craw(root_url)
</code>
2.url管理器 url_manager.py
<code>
#encoding:utf-8
'''
url管理器
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
class UrlManager(object):
def __init__(self):
#初始化两个url池
self.new_urls = set()
self.old_urls = set()
#向url管理器中添加一个新的url
def add_new_url(self, url):
#空数据不处理
if url is None:
return
#如果url没在未使用和已经使用的集合里,则添加进未使用的集合里
if url not in self.old_urls and url not in self.new_urls:
self.new_urls.add(url)
#向管理器中批量添加url
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
#是否有未爬取的url
def has_new_url(self):
return len(self.new_urls) != 0
#获取一个新的url
def get_new_url(self):
#从未访问的url集合中取一个url
new_url = self.new_urls.pop()
self.old_urls.add(new_url)
return new_url
</code>
3.网页下载器 html_downloader.py
<code>
#encoding:utf-8
'''
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
import urllib2
class HtmlDownloader(object):
#下载网页
def download(self, url):
if url is None:
return None
response = urllib2.urlopen(url)
#code=200表示能够正常访问
if response.getcode() != 200:
return None
return response.read()
</code>
4.网页解析器 html_parser.py
<code>
#encoding:utf-8
'''
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
import re
import urlparse
from bs4 import BeautifulSoup
if __name__ == '__main__':
pass
class HtmlParser(object):
def _get_new_urls(self, page_url, soup):
new_urls = set()
#目标链接形式
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 = {}
#url
res_data["url"] = page_url
#获取标题
#<dd class="lemmaWgt-lemmaTitle-title"><h1>Python</h1>
title_node = soup.find("dd", class_="lemmaWgt-lemmaTitle-title").find("h1")
res_data["title"] = title_node.get_text()
#获取简介
#<div class="lemma-summary" label-module="lemmaSummary">
summary_node = soup.find("div", class_="lemma-summary")
res_data["summary"] = summary_node.get_text()
return res_data
def parse(self, page_url, html_content):
if page_url is None or html_content is None:
return
soup = BeautifulSoup(html_content, "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
</code>
5.网页输出器 html_outputer.py
<code>
#encoding:utf-8
'''
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
class HtmlOutputer(object):
def __init__(self):
self.datas = []
def collect_data(self, data):
if data is None:
return
self.datas.append(data)
def output_html(self):
fout = open("output.html", "w")
fout.write("<html>")
fout.write("<body>")
fout.write("<table>")
#python默认编码为ascii
for data in self.datas:
fout.write("<tr>")
fout.write("<td>%s</td>" % data["url"])
#设置编码格式utf-8, 防止乱码
fout.write("<td>%s</td>" % data["title"].encode("utf-8"))
fout.write("<td>%s</td>" % data["summary"].encode("utf-8"))
fout.write("</tr>")
fout.write("</table>")
fout.write("</body>")
fout.write("</html>")
#关闭handler防止数据丢失
fout.close()
</code>
有效、批量下载数据的工具
二、简单爬虫架构
1.爬虫调度程序
2.url管理器
3.网页下载器
4.网页解析器
5.文件输出器
三、实现
此处将用python 2.7.9实现一个简单的爬虫,从python词条开始爬取1000条百度百科中的词条。
1.python urllib2下载网页的三种方式
(1)直接请求
import urllib2
#直接请求
response = urllib2.urlopen("www.baidu.com")
#获取状态码, 如果是200表是获取成功
print response.getcode()
#读取内容
content = response.read()
(2)添加data、http header
import urllib2
#创建request对象
request = urllib2.Request(url)
#添加数据
request.add_data("a", "1");
#添加http的header #伪装成火狐浏览器
request.add_header("User-agent", "Mozilla/5.0")
#发送请求, 获取结果
response = urllib2.urlopen(request)
(3)添加特殊情景的处理器
用户登录访问: HTTPCookieProcessor
代理访问: ProxyHandler
HTTPS协议: HTTPSHandler
自动跳转关系: HTTPRedirectHandler
#以上handler传送给urllib2
opener = urllib2.build_opener(handler)
#urllib2模块具有场景处理能力
urllib2.install_opener(opener)
#
urllib2.urlopen(url)
urllib2.urlopen(request)
<code>
#e.g. cookie增强版
import urllib2, cookielib
#创建cookie容器
cj = cookielib.CookieJar()
#创建1个opener
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
#给urllib2安装opener
urllib2.install_opener(opener)
#使用带有cookie的urllib2访问网页
response = urllib2.urlopen("www.baidu.com")
</code>
2.python的网页解析器
1)模糊匹配
正则表达式
2)结构化解析
html.parser
Beautiful Soup
lxml
3.Beautiful Soup语法
1)创建BeautifulSoup对象
#code
from bs4 import BeautifulSoup
#根据HTML网页字符串创建BeautifulSoup对象
soup = BeautifulSoup(
html_doc,
#HTML文档字符串
"html.parser",
#HTML解析器
from_encoding="utf-8"
#HTML文档编码格式
)
2)搜索节点(find_all, find)
# 方法: find_all(name, attrs, string) string参数为标签内容
#查找所有标签为a的节点
soup.find_all("a")
#查找所有标签为a,链接符合/view/123.html形式的节点
soup.find_all("a", href="/view/123.html")
soup.find_all("a", href=re.cpmpile(r'/view/\d+\.html') )
#正则形式
#查找所有标签为div, class为abc, 文字为python的节点
soup.find_all("div", class_="abc", string="python")
#class为python保留字,所以加下划线。
3)访问节点信息
#得到节点: <a href="1.html">python</a>
#获取查找到的节点的标签名称
node.name
#获取查找到的a节点的href属性
node["href"]
#获取查找的a节点的链接文字
node.get_text()
4)BeautifulSoup测试实例
<code>
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc, "html.parser", from_encoding="utf-8")
print "获取所有的链接"
links = soup.find_all("a")
for link in links:
print link.name, link["href"], link.get_text()
print "获取lacie的链接"
</code>
四、简单实例
1.调度程序 spider_main.py
<code>
#encoding:utf-8
'''
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
from com.baidu.baike_spider 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()
print "init SpiderMain success"
def craw(self, root_url): #开始爬取
#记录当前在爬取的url序号
count = 1
#初始化urls队列
self.urls.add_new_url(root_url)
#爬取循环
while self.urls.has_new_url():
#异常处理
try:
#获取新的url
new_url = self.urls.get_new_url()
print "crawing #%d : %s" %(count, new_url)
html_content = self.downloader.download(new_url)
new_urls, new_data = self.parser.parse(new_url, html_content)
self.urls.add_new_urls(new_urls)
self.outputer.collect_data(new_data)
#只爬取1000个页面
if count == 1000:
break
#计数器加1
count = count + 1
except:
print "craw failed"
self.outputer.output_html()
print "this job is done!"
if __name__ == "__main__":
root_url = "http://baike.baidu.com/view/21087.htm"
obj_spider = SpiderMain()
obj_spider.craw(root_url)
</code>
2.url管理器 url_manager.py
<code>
#encoding:utf-8
'''
url管理器
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
class UrlManager(object):
def __init__(self):
#初始化两个url池
self.new_urls = set()
self.old_urls = set()
#向url管理器中添加一个新的url
def add_new_url(self, url):
#空数据不处理
if url is None:
return
#如果url没在未使用和已经使用的集合里,则添加进未使用的集合里
if url not in self.old_urls and url not in self.new_urls:
self.new_urls.add(url)
#向管理器中批量添加url
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
#是否有未爬取的url
def has_new_url(self):
return len(self.new_urls) != 0
#获取一个新的url
def get_new_url(self):
#从未访问的url集合中取一个url
new_url = self.new_urls.pop()
self.old_urls.add(new_url)
return new_url
</code>
3.网页下载器 html_downloader.py
<code>
#encoding:utf-8
'''
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
import urllib2
class HtmlDownloader(object):
#下载网页
def download(self, url):
if url is None:
return None
response = urllib2.urlopen(url)
#code=200表示能够正常访问
if response.getcode() != 200:
return None
return response.read()
</code>
4.网页解析器 html_parser.py
<code>
#encoding:utf-8
'''
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
import re
import urlparse
from bs4 import BeautifulSoup
if __name__ == '__main__':
pass
class HtmlParser(object):
def _get_new_urls(self, page_url, soup):
new_urls = set()
#目标链接形式
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 = {}
#url
res_data["url"] = page_url
#获取标题
#<dd class="lemmaWgt-lemmaTitle-title"><h1>Python</h1>
title_node = soup.find("dd", class_="lemmaWgt-lemmaTitle-title").find("h1")
res_data["title"] = title_node.get_text()
#获取简介
#<div class="lemma-summary" label-module="lemmaSummary">
summary_node = soup.find("div", class_="lemma-summary")
res_data["summary"] = summary_node.get_text()
return res_data
def parse(self, page_url, html_content):
if page_url is None or html_content is None:
return
soup = BeautifulSoup(html_content, "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
</code>
5.网页输出器 html_outputer.py
<code>
#encoding:utf-8
'''
Created on 2015年12月31日
@author:Shawn Wang
@email:744585345@qq.com
'''
class HtmlOutputer(object):
def __init__(self):
self.datas = []
def collect_data(self, data):
if data is None:
return
self.datas.append(data)
def output_html(self):
fout = open("output.html", "w")
fout.write("<html>")
fout.write("<body>")
fout.write("<table>")
#python默认编码为ascii
for data in self.datas:
fout.write("<tr>")
fout.write("<td>%s</td>" % data["url"])
#设置编码格式utf-8, 防止乱码
fout.write("<td>%s</td>" % data["title"].encode("utf-8"))
fout.write("<td>%s</td>" % data["summary"].encode("utf-8"))
fout.write("</tr>")
fout.write("</table>")
fout.write("</body>")
fout.write("</html>")
#关闭handler防止数据丢失
fout.close()
</code>
相关文章推荐
- python中的迭代
- python 之 分割参数getopt
- 几种最短路径算的Python实现
- 不得不知道的Python字符串编码相关的知识
- Python3实现简单爬虫及一些编码问题
- Python学习笔记6-Python中re(正则表达式)模块学习
- Python学习笔记6-Python中re(正则表达式)模块学习
- Python学习笔记5-字符串、bool、数值操作和数组字典排序
- Python学习笔记5-字符串、bool、数值操作和数组字典排序
- 安装python和添加tab补齐的一系列问题
- python初级学习之基于收发邮件的远程控制程序
- python中的切片
- Python 一些常用模块的安装
- Python安装easy_install报错的处理方式
- leetcode之Bulb Switcher
- 第1章 Python简介
- 第2章 Python基础语法--Hello python
- win64位 安装python opencv
- super函数
- leetcode之Wiggle Sort II