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中列表和元组的相关语句和方法讲解
Aug 20 Python
基于Python代码编辑器的选用(详解)
Sep 13 Python
Python获取指定字符前面的所有字符方法
May 02 Python
Python实现模拟登录网易邮箱的方法示例
Jul 05 Python
Python图像处理之简单画板实现方法示例
Aug 30 Python
python 字符串常用函数详解
Sep 11 Python
python scipy卷积运算的实现方法
Sep 16 Python
Python 跨.py文件调用自定义函数说明
Jun 01 Python
Python CSS选择器爬取京东网商品信息过程解析
Jun 01 Python
python判断是空的实例分享
Jul 06 Python
基于Python采集爬取微信公众号历史数据
Nov 27 Python
python基于scrapy爬取京东笔记本电脑数据并进行简单处理和分析
Apr 14 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中call_user_func函数使用注意事项
2014/11/21 PHP
PHP模板引擎Smarty内建函数foreach,foreachelse用法分析
2016/04/11 PHP
php使用SAE原生Mail类实现各种类型邮件发送的方法
2016/10/10 PHP
php实时倒计时功能实现方法详解
2017/02/27 PHP
详解no input file specified 三种解决方法
2019/11/29 PHP
javascript 写类方式之八
2009/07/05 Javascript
js bind 函数 使用闭包保存执行上下文
2011/12/26 Javascript
jQuery div层的放大与缩小简单实现代码
2013/03/28 Javascript
jQuery 借助插件Lavalamp实现导航条动态美化效果
2013/09/27 Javascript
js倒计时小程序
2013/11/05 Javascript
jQuery的bind()方法使用详解
2015/07/15 Javascript
jQuery仿淘宝网产品品牌隐藏与显示效果
2015/09/01 Javascript
JavaScript编码风格指南(中文版)
2016/08/26 Javascript
原生JavaScript制作计算器
2016/10/16 Javascript
详解React Native开源时间日期选择器组件(react-native-datetime)
2017/09/13 Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
2018/07/03 Javascript
Vue条件循环判断+计算属性+绑定样式v-bind的实例
2018/09/18 Javascript
小程序云开发实战小结
2018/10/25 Javascript
详解vue-router数据加载与缓存使用总结
2018/10/29 Javascript
详解Angular Karma测试的持续集成实践
2019/11/15 Javascript
JavaScript实现多球运动效果
2020/09/07 Javascript
vue项目中播放rtmp视频文件流的方法
2020/09/17 Javascript
vue组件中传值EventBus的使用及注意事项说明
2020/11/16 Javascript
Python3+Appium实现多台移动设备操作的方法
2019/07/05 Python
使用Html5、CSS实现文字阴影效果
2018/01/17 HTML / CSS
英国街头品牌:Bee Inspired Clothing
2018/02/12 全球购物
文明餐桌活动方案
2014/02/11 职场文书
舞蹈毕业生的自我评价
2014/03/05 职场文书
家长学校实施方案
2014/03/15 职场文书
移风易俗倡议书
2014/04/15 职场文书
毕业生学校推荐信范文
2014/05/21 职场文书
2014县政府领导班子对照检查材料思想汇报
2014/09/25 职场文书
企业领导班子四风对照检查材料
2014/09/27 职场文书
大学军训的体会
2014/11/08 职场文书
初三数学教学反思
2016/02/17 职场文书
小学科学课教学反思
2016/02/23 职场文书