简单的爬虫实例

网络爬虫(web crawler)能够在无需人类干预的情况下自动进行一系列Web事务处理的软件程序。很多爬虫会从一个Web站点逛到另一个Web站点,获取内容,跟踪超链,并对它们找到的数据进行处理。
对于人来说手动去互联网上获取大量的需求数据时就会显得劳累了,而爬虫可以帮我我们解决这个问题。
本实例以爬取百度百科为例子,实现爬取百度百科的标题和一小段的介绍。

一、开发软件:eclipse
二、python3.7,说明一下这个版本有些模块与网上大多数的教程使用的用法稍有不同。
三、构建爬虫目录

1.调度器
2.下载器
3.url管理器
4.网页解析器
5.输出器


image.png

各个组件的联系如下图


爬虫架构.jpg

爬虫架构流程.jpg

对于网页解析器我们用的第三方插件是beautifulsoup4作为解析
爬虫解析器种类.jpg

四、各个组件的实现

在学习时代码以做了详细的注解,这里就直接上代码了

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("<html>")
    fout.write("<body>")
    fout.write("<table>")
    for data in self.datas:
        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("</table>")
    
    fout.write("</body>")
    
    fout.write("</html>")
    fout.close()

以上就是一个简单的爬虫实例,当设定的爬虫停止时,刷新界面就会看到在目录中多出了一个文件,打开就是我们想要的数据了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容

  • 本文主要实现一个简单的爬虫,目的是从一个百度贴吧页面下载图片。 1. 概述 本文主要实现一个简单的爬虫,目的是从一...
    m2fox阅读 1,612评论 0 1
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong阅读 22,388评论 1 92
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,649评论 18 139
  • 我坦然,于是我心美丽。 活着真叫累,有人这么感喟。活着真叫烦,更有人这么嘘叹。活着真的美丽,而我却喜欢这么对生活总...
    宛书阅读 165评论 0 0
  • 26年的岁月里,自己是个别人眼里的“书呆子”,不解风情,不修边幅,只知道一味的“傻学”。 随着年龄越来越长,自己在...
    苏凉1991阅读 569评论 0 2