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

一个简单的爬虫程序(爬取百度百科关于python的一千个页面)

2017-07-28 08:41 726 查看
最近学了点python基础,本着练手的目的跟着网上一个教程写了一个简单的爬虫程序。python入门还是很轻松的,整个过程也很顺利,几乎算是一次就成功了。

1.爬虫架构及工作流程

一个爬虫程序可以分为四个基本模块,总调度端,URL管理器,网页下载器以及网页解析器。

总调度段负责程序的启动,停止以及监视程序的运行进度。

URL管理器负责管理已经爬取过的URL和未爬取过的URL,它将未爬取过的网页URL发送给网页下载器并将该URL从为爬取URL列表删除。

网页下载器负责下载网页内容,转换成字符串形式(本程序中)发送给网页解析器。

网页解析器负责从爬取的网页内容中提取有价值的数据,本程序中有价值的数据为,网页中的URL以及词条名和词条简介。

2.各模块的实现

2.1 URL管理器的实现

网页URL可以存放到内存中(以set()的形式),MySQL数据库中以及redis缓存数据库中(大型项目)。本项目的URL以set()形式存放在内存中。

代码:

class UrlManager(object):

def __init__(self):
#初始化两个url集合
self.new_urls=set()#存放未爬取过的url
self.old_urls=set()#存放已爬取过的url
def add_new_url(self,url):#单个添加
if url is None:
return #如果是空的则不进行操作
if url not in self.new_urls and url not in self.old_urls:#全新的url
self.new_urls.add(url)

def has_new_url(self):#判断是否有未爬取的url
return len(self.new_urls)!=0

def get_new_url(self):
new_url = self.new_urls.pop()#从未怕去的url列表获取一个并移除
self.old_urls.add(new_url)
return new_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)


2.2 网页下载器的实现

有三种方法下载网页

1.下载最简单的网页(无需登录验证,没有加密…)

response = urllib.request.urlopen(url, data=None, timeout)

url: 需要打开的网址

data:Post提交的数据

timeout:设置网站的访问超时时间

page = response.read()

page = page.decode(‘utf-8’)#设置编码

2.先获取一个请求对象:urllib.request.Request(url, data=None, headers={}, method=None)

可以给包装请求对象设置header包装请求对象

header的参数

User-Agent :这个头部可以携带如下几条信息:浏览器名和版本号、操作系统名和版本号、默认语言

Referer:可以用来防止盗链,如果REFER的信息来自其他网站则禁止访问所需要的资源

Connection:表示连接状态,记录Session的状态。

request.add_header(‘user_agent’, ‘Mozilla/5.0’) 将程序伪装成火狐浏览器

3.处理一些特殊情景

HTTPCookieProcessor 登录验证问题

ProxyHandler 处理代理问题

HTTPRedirectHandler 处理会自动跳转的网页

(还没接触到,以后再说)

本程序使用的第一种方式,代码:

def download(self,url):
if url is None:

return None
request1 =urllib.request.urlopen(url)
if request1.getcode() !=200:#请求失败
return None
return request1.read()


3.网页解析器的实现

用到了BeautifulSoup第三方插件,实现这个功能时要审查待爬取的网页,找到自己要爬取的内容编码,便签,用来筛选数据。代码:

def get_new_urls(self, page_url, soup):
new_urls = set()
#         https://baike.baidu.com/item/Python links = soup.find_all('a',href=re.compile(r"/item/\S"))#查找页面中新的词条url
for link in links:
new_url = link['href']
new_full_url = urllib.parse.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
#<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,cont):
print('开始解析')
if page_url is None or cont is None:
return

soup = BeautifulSoup(cont,'html.parser',from_encoding='utf-8')
print('soup')
new_urls = self.get_new_urls(page_url,soup)
new_data = self.get_new_data(page_url,soup)

return new_urls,new_data


4.数据输出

将数据输出为html格式

def collect_data(self,data):
if data is None:
return None
self.datas.append(data)#将爬取的数据集合起来

def output_html(self):
fout = open('d:/output.html','w',encoding='utf-8')

fout.write("<html>")
fout.write("<body>")
fout.write("<table>")
fout.write("<tr>")
fout.write("<td>%s</td>"%'链接')
fout.write("<td>%s</td>"%'词条')
fout.write("<td>%s</td>"%'简介')
fout.write("</tr>")
for data in self.datas:
if data is None:
return None
fout.write("<tr>")
fout.write("<td>%s</td>" % data['url'])
fout.write("<td>%s</td>" % data['title'])
fout.write("<td>%s</td>" % data['summary'])
fout.write("</tr>")
fout.write("</html>")
fout.write("</body>")
fout.write("</table>")


5.程序调度

按顺序调用以上各个方法就好了,代码:

class SpiderMain(object):
def __init__(self):
self.url = url_manager.UrlManager()
self.downloader = html_downloader.HtmlDownLoader()
self.parser = html_parser.HtmlParser()
self.outputer = html_outputer.OutPuter()

def craw(self, root_url):
count = 1 #记录当前爬取的是第几个url
self.url.add_new_url(root_url)#把初始url添加到url管理器

while self.url.has_new_url():#当管理器里仍有未爬取url时
try:
new_url=self.url.get_new_url()#从管理器中拿出一个url
print('craw %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列表,和爬取到的数据
self.url.add_new_urls(new_urls) #将新的url添加到管理器,注意于添加root_url的方法不同
self.outputer.collect_data(new_data)#收集数据

if count==1000:#只爬取1000条
break

count+=1
except:
print('爬取失败')

self.outputer.output_html()#将收集的数据输出

if __name__ == '__main__':
root_url='https://baike.baidu.com/item/Python'
obj_spider = SpiderMain()
obj_spider.craw(root_url)#启动爬虫程序
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: