继续上一篇文章的内容,上一篇文章中已经将url管理器和下载器写好了。接下来就是url解析器,总的来说这个模块是几个模块中比较难的。因为通过下载器下载完页面之后,我们虽然得到了页面,但是这并不是我们想要的结果。而且由于页面的代码很多,我们很难去里面找到自己想要的数据。所幸,我们下载的是html页面,它是一种由多个多层次的节点组成的树型结构的文本文件。所以,相较于txt文件,我们更加容易定位到我们要找的数据块。现在我们要做的就是去原页面去分析一下,我们想要的数据到底在哪。

  打开百度百科pyton词条的页面,然后按F12调出开发者工具。通过使用工具,我们就能定位到页面的内容:

  这样我们就找到了我们想要的信息处在哪个标签里了。

 import bs4
 import re
 from urllib.parse import urljoin
 class HtmlParser(object):
     """docstring for HtmlParser"""
     def _get_new_urls(self, url, soup):
         new_urls = set()
         links = soup.find_all('a', href = re.compile(r'/item/.'))
         for link in links:
             new_url = re.sub(r'(/item/)(.*)', r'\1%s' % link.getText(), link['href'])
             new_full_url = urljoin(url, new_url)
             new_urls.add(new_full_url)
         return new_urls

     def _get_new_data(self, url, soup):
         res_data = {}
         #url
         res_data['url'] = url
         #<dd class="lemmaWgt-lemmaTitle-title">
         title_node = soup.find('dd', class_ = "lemmaWgt-lemmaTitle-title").find('h1')
         res_data['title'] = title_node.getText()
         #<div class="lemma-summary" label-module="lemmaSummary">
         summary_node = soup.find('div', class_ = "lemma-summary")
         res_data['summary'] = summary_node.getText()
         return res_data

     def parse(self, url, html_cont):
         if url is None or html_cont is None:
             return
         soup = bs4.BeautifulSoup(html_cont, 'lxml')
         new_urls = self._get_new_urls(url, soup)
         new_data = self._get_new_data(url, soup)
         return new_urls, new_data

  解析器只有一个外部方法就是parse方法,

    a.首先它会接受url, html_cont两个参数,然后进行判断页面内容是否为空

    b.调用bs4模块的方法来解析网页内容,'lxml'为文档解析器,默认的为html.parser,bs官方推荐我们用lxml,那就听它的吧,谁让人家是官方呢。

    c.接下来就是调用两个内部函数来获取新的url列表和数据

    d.最后将url列表和数据返回

  这里有一些注意点

    1.bs的方法调用还有一个参数,from_encoding 这个和我在下载器那里的重复了,所以我就取消了,两个的功能是一样的。

    2.获取url列表的内部方法,需要用到正则表达式,这里我也是摸着石头过河,不是很会,中间也调试过许多次。

    3.数据是放在字典中的,这样可以通过key来增改删除数据。

最好,就直接数据输出了,这个比较简单,直接上代码。

  

 class HtmlOutputer(object):
     """docstring for HtmlOutputer"""
     def __init__(self):
         self.datas = []
     def collect_data(self, new_data):
         if new_data is None:
             return
         self.datas.append(new_data)
     def output_html(self):
         fout = open('output1.html', 'w', encoding = 'utf-8')
         fout.write('<html>')
         fout.write('<head><meta charset="utf-8"></head>')
         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()

  这里也有两个注意点

    1.fout = open('output1.html', 'w', encoding = 'utf-8'),这里的encoding参数一定要加,不然会报错,在windows平台,它默认是使用gbk编码来写文件的。

    2.fout.write('<head><meta charset="utf-8"></head>'),这里的meta标签也要加上,因为要告诉浏览器使用什么编码来渲染页面,这里我一开始没加弄了很久,我打开页面的内容,发现里面是中文的,结果浏览器展示的就是乱码。总的来说,因为整个页面采集过程结果好几个模块,所以编码问题要非常小心,不然少不留神就会出错。

  最后总结,这段程序还有许多方面可以深入探讨:

  1.页面的数据量过小,我尝试了10000个页面的爬取。一旦数据量剧增之后,就会带来一下问题,第一是待爬取url和已爬取url就不能放在set集合中了,要么放到radi缓存服务器里,要么放到mysql数据库中

  2.第二,数据也是同样的,字典也满足不了了,需要专门的数据库来存放

  3.第三量上去之后,对爬取效率就有要求了,那么多线程就要加进来

  4.第四,一旦布置好任务,单台服务器的压力会过大,而且一旦宕机,风险很大,所以分布式的高可用架构也要跟上来

  5.一方面是页面的内容过于简单,都是静态页面,不涉及登录,也不涉及ajax动态获取

  6.这只是数据采集,后续还有建模,分析…………

综上所述,路还远的很呢,加油!

  

python——爬虫&问题解决&思考(四)的更多相关文章

  1. python——爬虫&问题解决&思考(1)

    最近刚接触python,找点小任务来练练手,希望自己在实践中不断的锻炼自己解决问题的能力.这个小爬虫来自慕课网的一门课程,我在这里记录的是自己学习的过程中遇到的问题和解决方法以及爬虫之外的思考. 这次 ...

  2. python——爬虫&问题解决&思考(三)

    继续上一篇文章的内容,上一篇文章中,将爬虫调度器已经写好了,调度器是整个爬虫程序的"大脑",也可以称之为指挥中心.而现在,我们要做的就是去将调度器中用到的其他组件写好.首先是url ...

  3. Python爬虫学习:四、headers和data的获取

    之前在学习爬虫时,偶尔会遇到一些问题是有些网站需要登录后才能爬取内容,有的网站会识别是否是由浏览器发出的请求. 一.headers的获取 就以博客园的首页为例:http://www.cnblogs.c ...

  4. python爬虫入门(四)利用多线程爬虫

    多线程爬虫 先回顾前面学过的一些知识 1.一个cpu一次只能执行一个任务,多个cpu同时可以执行多个任务2.一个cpu一次只能执行一个进程,其它进程处于非运行状态3.进程里包含的执行单元叫线程,一个进 ...

  5. Python 爬虫入门(四)—— 验证码上篇(主要讲述验证码验证流程,不含破解验证码)

    本篇主要讲述验证码的验证流程,包括如何验证码的实现.如何获取验证码.识别验证码(这篇是人来识别,机器识别放在下篇).发送验证码.同样以一个例子来说明.目标网址 http://icp.alexa.cn/ ...

  6. Python爬虫(二十四)_selenium案例:执行javascript脚本

    本章叫介绍如何使用selenium在浏览器中使用js脚本,更多内容请参考:Python学习指南 隐藏百度图片 #-*- coding:utf-8 -*- #本篇将模拟执行javascript语句 fr ...

  7. python爬虫入门---第四篇:网站对爬虫的限制及突破测试

    大部分网站对网络爬虫都有限制,限制方式有两种: 一.Robots协议:二.网站通过判断对网站访问http的头部信息来查看是否是爬虫,并对爬虫做相关拦截 第一种限制是书面限制,第二种是强制性阻拦限制.那 ...

  8. Python爬虫基础(四)Requests库的使用

    requests文档 首先需要安装:pip install requests get请求 最基本的get: # -*- coding: utf-8 -*-import requests respons ...

  9. python爬虫---实现项目(四) 用BeautifulSoup分析新浪新闻数据

    这次只演示了,如何在真实项目内用到BeautifulSoup库来解析网页,而新浪的新闻是ajax加载过来的数据,在这里我们只演示解析部分数据(具体反扒机制没做分析). 代码地址:https://git ...

随机推荐

  1. js的break语句,continue语句,return语句

    js的break语句,continue语句,return语句. 用的时候很容易混淆,有过一次泪奔的经历. break语句 break语句会使运行的程序立刻退出包含在最内层的循环或者退出一个switch ...

  2. 初遇stm32

    刚开始接触32,建一个工程都这么费劲,可能是keil安装时一些文件和库没有安装完整,真是坑啊. 回头可能还要从新安装,然后开始新的学习,争取十天之内入门32,在博客园这个强大的技术支持下, 想不入门都 ...

  3. JS的块级作用域

    今天带来的是 "对<你不知道的js>中块级作用域的总结" 分享: 1)用with从对象中创建出来的作用域只在with声明中而非外部作用域有效,同时可以访问已有对象的属性 ...

  4. ActiveMQ学习心得:连接池的简单实现和模板模式的应用

    一.安装activemq 下载地址:https://archive.apache.org/dist/activemq/5.13.0/apache-activemq-5.13.0-bin.zip 下载完 ...

  5. Linux 基础(3)

    Linux 基础(三) rpm与yum学习 本篇分享一下自己学习rpm和yum过程中的一些心得,自己在使用yum过程中由于自己的虚拟机网络的问题在学习这一块品尝到不少苦头,还望学习这块的盆友先检查一下 ...

  6. 【知识学习】如何寻找真实IP

    1.多地点ping查询IP,如果都一样可能没有使用cdn,如果有cdn,尝试海外地点ping查询IP 2.ping一下没有WWW的域名,可能存在真实IP.比如www.baidu.com设置了cdn,那 ...

  7. 我拖拖拖--H5拖放API基础篇

    不要搞错,本文不是讲如何拖地的.看过<javascript精粹>朋友应该知道,他实现拖放的过程比较复杂,现在时代不同了,我们用H5的新的拖放API就能非常方便的实现拖放效果了.最近在园子见 ...

  8. cin 字符串输入

    cin 字符串输入 在学习c的时候,关于字符串的输入,记得有 scanf("%s",s); gets(s); 还有...o.o 好想没了... scanf("%s&quo ...

  9. poj1751最小生成树

    The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has a very poor system of p ...

  10. python课程第一天笔记-la

    http://www.cnblogs.com/onda/   ----------------------20170423 一:Cpython  pypy 区别 等;Cpython 是一行一行解释, ...