网络爬虫(web crawler)能够在无需人类干预的情况下自动进行一系列Web事务处理的软件程序。很多爬虫会从一个Web站点逛到另一个Web站点,获取内容,跟踪超链,并对它们找到的数据进行处理。
对于人来说手动去互联网上获取大量的需求数据时就会显得劳累了,而爬虫可以帮我我们解决这个问题。
本实例以爬取百度百科为例子,实现爬取百度百科的标题和一小段的介绍。
一、开发软件:eclipse
二、python3.7,说明一下这个版本有些模块与网上大多数的教程使用的用法稍有不同。
三、构建爬虫目录
1.调度器
2.下载器
3.url管理器
4.网页解析器
5.输出器
各个组件的联系如下图
对于网页解析器我们用的第三方插件是beautifulsoup4作为解析
四、各个组件的实现
在学习时代码以做了详细的注解,这里就直接上代码了
1调度器:
'''
Created on 2018年6月1日
@author: Administrator
'''
#爬虫总调程序
#爬虫总调函数会以一个url作为入口 参数来爬取相关页面
from baike_spiler import url_manager, html_download, html_output, html_parser2
#首先编写main函数
class SpiderMain(object):
def __init__(self):
#创建并初始化url管理器、下载管理器、解析器、输出器
self.urls=url_manager.UrlManager()
self.downloader=html_download.HtmlDownloader()
self.parser=html_parser2.HtmlParser2()
self.outputer=html_output.Html_output()
def craw(self, root_url):
#记录爬取的次数
count=1
#将入口url添加入url管理器
#以下方法需要自己实现
self.urls.add_new_url(root_url)
#当url中有待爬取的url启动爬虫循环,循环爬取相关的url数据
while self.urls.has_new_url():
try:
#获取一个url
new_url=self.urls.get_new_url()
print(count,new_url)
#将下载结果存到下载器中
html_cont=self.downloader.downloader(new_url)
#调用解析器来解析下载的页面,得到新的列表及新的数组,传入当前爬取的url以及下载好的页面数据
new_urls,new_data=self.parser.parse(new_url,html_cont)
#将得到的url和数据进行处理,将url添加入url管理器及用输出器收集数据
self.urls.add_new_urls(new_urls)
self.outputer.collect_data(new_data)
if count>10:
break
count=count+1
except:
print("crap fail")
#调用输出管理器输出处理好的数据
self.outputer.output_html()
if __name__=="__main__":
#设置要爬取的入口url
root_url="https://baike.baidu.com/item/Python/407313"
#创建一个spider
obj_spider=SpiderMain()
#调用craw方法来启动爬虫
obj_spider.craw(root_url)
2、下载器
'''
Created on 2018年6月1日
@author: Administrator
'''
import urllib.request
class HtmlDownloader(object):
def downloader(self,url):
if url is None:
print("none")
return None
#引用urllib2模块
req=urllib.request.Request(url)
# #设置请求头,伪装成motila浏览器
#req.add_header("User-Agent","Mozilla/5.0")
response5=urllib.request.urlopen(req)
#response5=urllib.request.urlopen(url)
if response5.getcode() !=200:
return None
#print(response5.read().decode('utf-8'))
return response5.read().decode('utf-8')
3、URL管理器
'''
Created on 2018年6月1日
@author: Administrator
'''
#url管理器
class UrlManager(object):
def __init__(self):
#各个函数进行初始化
#set()是使用内存来实现url管理器,系统实现
self.new_urls=set()
self.old_urls=set()
def add_new_url(self,url):
#判断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):
#如果new_urls这个列表不为0
return len(self.new_urls) !=0
def add_new_urls(self,urls):#这个是批量添加urls
if urls is None and len(urls)==0:
return
for url in urls:
#进行逐个添加
self.add_new_url(url)
def get_new_url(self):
#首先获取一个url,使用系统pop()方法
new_url=self.new_urls.pop()
return new_url
4、网页解析器
'''
Created on 2018年6月1日
@author: Administrator
'''
#HTML解析器
from bs4 import BeautifulSoup
import re
from urllib.parse import urlparse
from urllib.parse import urljoin
class HtmlParser2(object):
def _get_new_urls(self, page_url, soup):
#将解析出来的url存到一个集合中
new_urls=set()#生成一个集合
#匹配url,如/view/123.htm
links = soup.find_all('a', href=re.compile(r"/item/.*"))
for link in links:
new_url=link['href']
#使用urljoin拼接两个url
new_full_url=urljoin(page_url,new_url)
new_urls.add(new_full_url)
#print(new_urls)
return new_urls
def _get_new_data(self, page_url, soup):
#先建立一个字典来存放数据
res_data={}
res_data['url']=page_url
#print("url")
title_node =soup.find('dd',class_="lemmaWgt-lemmaTitle-title").find("h1")
res_data['title']=title_node.get_text()
#print("title")
summary_node=soup.find('div',class_="lemma-summary")
res_data['summary']=summary_node.get_text()
print(res_data)
return res_data
def parse(self,page_url,html_cont):
if page_url is None or html_cont is None:
return
#调用beautifulsoup解析器
soup=BeautifulSoup(html_cont,'html.parser',from_encoding='utf-8')
#print(soup)
#调用两个本类方法
new_urls=self._get_new_urls(page_url,soup)#从下载的网页中获取url
new_data=self._get_new_data(page_url,soup)#从下载的网页中获取数据
#print("new_data")
return new_urls,new_data
5、输出器(以html形式输出)
'''
Created on 2018年6月1日
@author: Administrator
'''
#把数据通过html展示
class Html_output(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('coutput.html','w',encoding='utf-8')
fout.write("")
fout.write("")
fout.write("")
for data in self.datas:
fout.write("")
fout.write("%s "% data['url'])
fout.write("%s "% data['title'])
fout.write("%s "% data['summary'])
fout.write(" ")
fout.write("
")
fout.write("")
fout.write("")
fout.close()
以上就是一个简单的爬虫实例,当设定的爬虫停止时,刷新界面就会看到在目录中多出了一个文件,打开就是我们想要的数据了。