您的位置:首页 > 编程语言 > Python开发

使用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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: