Python爬虫实现爬取百度百科词条功能实例


Posted in Python onApril 05, 2019

本文实例讲述了Python爬虫实现爬取百度百科词条功能。分享给大家供大家参考,具体如下:

爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成。爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL,在抓取网页的过程中,不断从当前页面上抽取新的URL放入队列,直到满足系统的一定停止条件。爬虫的工作流程较为复杂,需要根据一定的网页分析算法过滤与主题无关的链接,保留有用的链接并将其放入等待抓取的URL队列。然后,它将根据一定的搜索策略从队列中选择下一步要抓取的网页URL,并重复上述过程,直到达到系统的某一条件时停止。另外,所有被爬虫抓取的网页将会被系统存贮,进行一定的分析、过滤,并建立索引,以便之后的查询和检索。常见的爬虫框架有Scrapy等。

自定义爬虫程序一般包含:URL管理器、网页下载器、网页解析器、输出处理器。

以下我写了一个爬取百度百科词条的实例。

爬虫主程序入口

from crawler_test.html_downloader import UrlDownLoader
from crawler_test.html_outer import HtmlOuter
from crawler_test.html_parser import HtmlParser
from crawler_test.url_manager import UrlManager
# 爬虫主程序入口
class MainCrawler():
  def __init__(self):
    # 初始值,实例化四大处理器:url管理器,下载器,解析器,输出器
    self.urls = UrlManager()
    self.downloader = UrlDownLoader()
    self.parser = HtmlParser()
    self.outer = HtmlOuter()
  # 开始爬虫方法
  def start_craw(self, main_url):
    print('爬虫开始...')
    count = 1
    self.urls.add_new_url(main_url)
    while self.urls.has_new_url():
      try:
        new_url = self.urls.get_new_url()
        print('爬虫%d,%s' % (count, new_url))
        html_cont = self.downloader.down_load(new_url)
        new_urls, new_data = self.parser.parse(new_url, html_cont)
        # 将解析出的url放入url管理器,解析出的数据放入输出器中
        self.urls.add_new_urls(new_urls)
        self.outer.conllect_data(new_data)
        if count >= 10:# 控制爬取的数量
          break
        count += 1
      except:
        print('爬虫失败一条')
    self.outer.output()
    print('爬虫结束。')
if __name__ == '__main__':
  main_url = 'https://baike.baidu.com/item/Python/407313'
  mc = MainCrawler()
  mc.start_craw(main_url)

URL管理器

# URL管理器
class UrlManager():
  def __init__(self):
    self.new_urls = set() # 待爬取
    self.old_urls = set() # 已爬取
  # 添加一个新的url
  def add_new_url(self, url):
    if url is None:
      return
    elif url not in self.new_urls and url not in self.old_urls:
      self.new_urls.add(url)
  # 批量添加url
  def add_new_urls(self, urls):
    if urls is None or len(urls) == 0:
      return
    else:
      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):
    new_url = self.new_urls.pop()
    self.old_urls.add(new_url)
    return new_url

网页下载器

from urllib import request
# 网页下载器
class UrlDownLoader():
  def down_load(self, url):
    if url is None:
      return None
    else:
      rt = request.Request(url=url, method='GET')   # 发GET请求
      with request.urlopen(rt) as rp:         # 打开网页
        if rp.status != 200:
          return None
        else:
          return rp.read()            # 读取网页内容

网页解析器

import re
from urllib import parse
from bs4 import BeautifulSoup
# 网页解析器,使用BeautifulSoup
class HtmlParser():
  # 每个词条中,可以有多个超链接
  # main_url指url公共部分,如“https://baike.baidu.com/”
  def _get_new_url(self, main_url, soup):
    # baike.baidu.com/
    # <a target="_blank" href="/item/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80" rel="external nofollow" >计算机程序设计语言</a>
    new_urls = set()
    # 解析出main_url之后的url部分
    child_urls = soup.find_all('a', href=re.compile(r'/item/(\%\w{2})+'))
    for child_url in child_urls:
      new_url = child_url['href']
      # 再拼接成完整的url
      full_url = parse.urljoin(main_url, new_url)
      new_urls.add(full_url)
    return new_urls
  # 每个词条中,只有一个描述内容,解析出数据(词条,内容)
  def _get_new_data(self, main_url, soup):
    new_datas = {}
    new_datas['url'] = main_url
    # <dd class="lemmaWgt-lemmaTitle-title"><h1>计算机程序设计语言</h1>...
    new_datas['title'] = soup.find('dd', class_='lemmaWgt-lemmaTitle-title').find('h1').get_text()
    # class="lemma-summary" label-module="lemmaSummary"...
    new_datas['content'] = soup.find('div', attrs={'label-module': 'lemmaSummary'},
                     class_='lemma-summary').get_text()
    return new_datas
  # 解析出url和数据(词条,内容)
  def parse(self, main_url, html_cont):
    if main_url is None or html_cont is None:
      return
    soup = BeautifulSoup(html_cont, 'lxml', from_encoding='utf-8')
    new_url = self._get_new_url(main_url, soup)
    new_data = self._get_new_data(main_url, soup)
    return new_url, new_data

输出处理器

# 输出器
class HtmlOuter():
  def __init__(self):
    self.datas = []
  # 先收集数据
  def conllect_data(self, data):
    if data is None:
      return
    self.datas.append(data)
    return self.datas
  # 输出为HTML
  def output(self, file='output_html.html'):
    with open(file, 'w', encoding='utf-8') as fh:
      fh.write('<html>')
      fh.write('<head>')
      fh.write('<meta charset="utf-8"></meta>')
      fh.write('<title>爬虫数据结果</title>')
      fh.write('</head>')
      fh.write('<body>')
      fh.write(
        '<table style="border-collapse:collapse; border:1px solid gray; width:80%; word-break:break-all; margin:20px auto;">')
      fh.write('<tr>')
      fh.write('<th style="border:1px solid black; width:35%;">URL</th>')
      fh.write('<th style="border:1px solid black; width:15%;">词条</th>')
      fh.write('<th style="border:1px solid black; width:50%;">内容</th>')
      fh.write('</tr>')
      for data in self.datas:
        fh.write('<tr>')
        fh.write('<td style="border:1px solid black">{0}</td>'.format(data['url']))
        fh.write('<td style="border:1px solid black">{0}</td>'.format(data['title']))
        fh.write('<td style="border:1px solid black">{0}</td>'.format(data['content']))
        fh.write('</tr>')
      fh.write('</table>')
      fh.write('</body>')
      fh.write('</html>')

效果(部分):

Python爬虫实现爬取百度百科词条功能实例

更多关于Python相关内容可查看本站专题:《Python Socket编程技巧总结》、《Python正则表达式用法总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
打印出python 当前全局变量和入口参数的所有属性
Jul 01 Python
Python脚本实现集群检测和管理功能
Mar 06 Python
Python抓取百度查询结果的方法
Jul 08 Python
删除DataFrame中值全为NaN或者包含有NaN的列或行方法
Nov 06 Python
python实现海螺图片的方法示例
May 12 Python
Python中Numpy mat的使用详解
May 24 Python
python自动发微信监控报警
Sep 06 Python
Python树莓派学习笔记之UDP传输视频帧操作详解
Nov 15 Python
查看端口并杀进程python脚本代码
Dec 17 Python
使用Python将图片转正方形的两种方法实例代码详解
Apr 29 Python
基于pandas向csv添加新的行和列
May 25 Python
python tqdm实现进度条的示例代码
Nov 10 Python
Python3.5多进程原理与用法实例分析
Apr 05 #Python
Python选择网卡发包及接收数据包
Apr 04 #Python
详解Python的数据库操作(pymysql)
Apr 04 #Python
python dlib人脸识别代码实例
Apr 04 #Python
python图像处理入门(一)
Apr 04 #Python
python爬虫简单的添加代理进行访问的实现代码
Apr 04 #Python
Django项目中添加ldap登陆认证功能的实现
Apr 04 #Python
You might like
php实例分享之html转为rtf格式
2014/06/02 PHP
PHP常用正则表达式集锦
2014/08/17 PHP
php中的字符编码转换函数用法示例
2014/10/20 PHP
php中文验证码实现方法
2015/06/18 PHP
php快速排序原理与实现方法分析
2016/05/26 PHP
PHP在同一域名下两个不同的项目做独立登录机制详解
2017/09/22 PHP
jQuery选中select控件 无法设置selected的解决方法
2010/09/01 Javascript
JS无限极树形菜单,json格式、数组格式通用示例
2013/07/30 Javascript
Javascript this 关键字 详解
2014/10/22 Javascript
JavaScript数据结构与算法之集合(Set)
2016/01/29 Javascript
jQuery ajax应用总结
2016/06/02 Javascript
AngularJS中的缓存使用
2017/01/11 Javascript
vue数据双向绑定的注意点
2017/06/23 Javascript
JS实现的JSON数组去重算法示例
2018/04/11 Javascript
JavaScript对象的浅拷贝与深拷贝实例分析
2018/07/25 Javascript
Bootstrap导航菜单点击后无法自动添加active的处理方法
2018/08/10 Javascript
对angularJs中2种自定义服务的实例讲解
2018/09/30 Javascript
微信小程序对图片进行canvas压缩的方法示例详解
2020/11/12 Javascript
python使用clear方法清除字典内全部数据实例
2015/07/11 Python
python或C++读取指定文件夹下的所有图片
2019/08/31 Python
python加载自定义词典实例
2019/12/06 Python
Django操作session 的方法
2020/03/09 Python
Django-rest-framework中过滤器的定制实例
2020/04/01 Python
python json.dumps() json.dump()的区别详解
2020/07/14 Python
Python常驻任务实现接收外界参数代码解析
2020/07/21 Python
html5基础标签(html5视频标签 html5新标签用法)
2013/12/30 HTML / CSS
澳大利亚男士西服品牌:M.J.Bale
2018/02/06 全球购物
HelloFresh奥地利:立即订购烹饪盒
2019/02/22 全球购物
瑞典在互联网上最大的宠物商店:Animail
2020/10/31 全球购物
奥巴马开学演讲稿
2014/05/15 职场文书
2014年教师节演讲稿范文
2014/09/10 职场文书
小学教师岗位职责
2015/04/02 职场文书
2015年信息化建设工作总结
2015/07/23 职场文书
Python中使用Lambda函数的5种用法
2021/04/01 Python
Apache Hudi的多版本清理服务彻底讲解
2022/03/31 Servers
类和原型的设计模式之复制与委托差异
2022/07/07 Javascript