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新手在作用域方面经常容易碰到的问题
Apr 03 Python
研究Python的ORM框架中的SQLAlchemy库的映射关系
Apr 25 Python
python3抓取中文网页的方法
Jul 28 Python
利用python获取某年中每个月的第一天和最后一天
Dec 15 Python
python中闭包Closure函数作为返回值的方法示例
Dec 17 Python
python 获取list特定元素下标的实例讲解
Apr 09 Python
python中pika模块问题的深入探究
Oct 13 Python
Python定时发送消息的脚本:每天跟你女朋友说晚安
Oct 21 Python
Pycharm配置远程调试的方法步骤
Dec 17 Python
PyCharm的设置方法和第一个Python程序的建立
Jan 16 Python
解决Windows下python和pip命令无法使用的问题
Aug 31 Python
用Python仅20行代码编写一个简单的端口扫描器
Apr 08 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连接数据库代码应用分析
2011/05/29 PHP
php输出echo、print、print_r、printf、sprintf、var_dump的区别比较
2013/06/21 PHP
php使用递归计算文件夹大小
2014/12/24 PHP
php实现计数器方法小结
2015/01/05 PHP
php如何实现只替换一次或N次
2015/10/29 PHP
详解PHP匿名函数与注意事项
2016/03/29 PHP
降低PHP Redis内存占用
2017/03/23 PHP
php通过pecl方式安装扩展的实例讲解
2018/02/02 PHP
使用dynatrace-ajax跟踪JavaScript的性能
2010/04/12 Javascript
JavaScript与Div对层定位和移动获得坐标的实现代码
2010/09/08 Javascript
纯js实现背景图片切换效果代码
2010/11/14 Javascript
基于jquery的监控数据是否发生改变
2011/04/11 Javascript
Node.js实现的简易网页抓取功能示例
2014/12/05 Javascript
Angular用来控制元素的展示与否的原生指令介绍
2015/01/07 Javascript
DOM节点深度克隆函数cloneNode()用法实例
2015/01/12 Javascript
jQuery取消ajax请求的方法
2015/06/09 Javascript
jquery移动端TAB触屏切换实现效果
2020/12/22 Javascript
jQuery实现的文字hover颜色渐变效果实例
2016/02/20 Javascript
jQuery自适应轮播图插件Swiper用法示例
2016/08/24 Javascript
Vuejs第九篇之组件作用域及props数据传递实例详解
2016/09/05 Javascript
深入探讨Vue.js组件和组件通信
2016/09/12 Javascript
URL的参数中有加号传值变为空格的问题(URL特殊字符)
2016/11/04 Javascript
Javascript数组循环遍历之forEach详解
2016/11/07 Javascript
JavaScript简单生成 N~M 之间随机数的方法
2017/01/13 Javascript
微信小程序实现图片预加载组件
2017/01/18 Javascript
详解Angular之constructor和ngOnInit差异及适用场景
2017/06/22 Javascript
详解webpack 如何集成第三方js库
2017/06/29 Javascript
解决vue中修改了数据但视图无法更新的情况
2018/08/27 Javascript
Python中的Numpy矩阵操作
2018/08/12 Python
Anaconda2 5.2.0安装使用图文教程
2018/09/19 Python
python程序运行进程、使用时间、剩余时间显示功能的实现代码
2019/07/11 Python
python框架flask入门之环境搭建及开启调试
2020/06/07 Python
详解python实现可视化的MD5、sha256哈希加密小工具
2020/09/14 Python
PyCharm最新激活码PyCharm2020.2.3有效
2020/11/18 Python
植树造林的宣传标语
2014/06/23 职场文书
毕业生代领毕业材料的授权委托书
2014/09/29 职场文书