前段时间,一朋友让我做个小脚本,抓一下某C2C商城上竞争对手的销售/价格数据,好让他可以实时调整自己的营销策略。自己之前也有过写爬虫抓某宝数据的经历,实现的问题不大,于是就答应了。初步想法是利用pyhton中的urllib.request和re两个lib(本文示例用的是Pyhton 3.4 ,2.x的请自行切换),外加上其他的统计分析功能的话,最多两个晚上(白天要工作)可以搞定。实际上做的过程中,遇到了两个主要困难:
(1)电商网站对于交易数据的保护很好。小爬虫动不动就会被ban掉或者采用一些其他的保护措施使得其无法正常采集所需的数据,需要添加额外的代码处理各种虐心的情况;
(2)正则表达式实在是难写,而且很复杂和很难维护。于是自己也思考有没有其他的解决方案——本文就是对其中一解决方案的初步介绍。
 
一开始想到的当然是著名的第三方库Beautifulsoup(作为一个广东男人,我习惯把它称为”靓汤“)。这个库很强大,但正因为它强大,需要一点学习时间而我需要快点上手,于是只好日后再学(到时再写一篇Beautifulsoup学习总结)。权衡以后,最后目光转向了Python Standard Library中的html.parser。
 
html.parser是一个非常简单和实用的库,它的核心是HTMLParser类。从源码来看,它内部封装了一系列regular expression。工作的流程是:当你feed给它一个类似HTML格式的字符串时,它会调用goahead方法向前迭代各个标签,并调用对应的parse_xxxx方法提取start_tag, tag, attrs data comment和end_tag等等标签信息和数据,然后调用对应的方法对这些抽取出来的内容进行处理。整个HTMLParser的大致结构如下图所示:
 
 
 
可以发现,处理开始标签(handle_starttag)、结束标签(handle_endtag)和处理数据(handle_data)等处理函数在HTMLParser里是没有实现的(pass),这需要我们继承HTMLParser这个类的并覆盖这些方法。详细可以参阅python文档,这里重点介绍几个常用的方法:
 
  1. feed(data):主要用于接受带html标签的str,当调用这个方法时并提供相应的data时,整个实例(instance)开始执行,结束执行close()。
  2. handle_starttag(tag, attrs): 这个方法接收Parse_starttag返回的tag和attrs,并进行处理,处理方式通常由使用者进行覆盖,本身为空。例如,连接的start tag是<a>,那么对应的参数tag=’a’(小写)。attrs是start tag <>中的属性,以元组形式(name, value)返回(所有这些内容都是小写)。例如,对于<A HREF="http://www.baidu.com“>,那么内部调用形式为:handle_starttag(’a’,[(‘href’,’http://www.baidu.com)]).
  3. handle_endtag(tag):跟上述一样,只是处理的是结束标签,也就是以</开头的标签。
  4. handle_data(data):处理的是网页的数据,也就是开始标签和结束标签之间的内容。例如:<script>...</script>的省略号内容
  5. reset():将实例重置,包括作为参数输入的数据进行清空。
 
举个例子吧。例如我们有以下一堆带HTML标签的数据,

     【金冠现货/全色/顶配版】Xiaomi/小米 小米note移动联通4G手机
   </h3>
   <p class="tb-subtitle">
 【购机即送布丁套+高清贴膜+线控耳机+剪卡器+电影支架等等,套餐更多豪礼更优惠】    【购机即送布丁套+高清贴膜+线控耳机+剪卡器+电影支架等等,套餐更多豪礼更优惠】    【金冠信誉+顺丰包邮+全国联保---多重保障】
 </p>
   <div id="J_TEditItem" class="tb-editor-menu"></div>
 </div>
<h3 class="tb-main-title" data-title="【现货增强/标准】MIUI/小米 红米手机2红米2移动联通电信4G双卡">
     【现货增强/标准】MIUI/小米 红米手机2红米2移动联通电信4G双卡
   </h3>
   <p class="tb-subtitle">
 [红米手机2代颜色版本较多,请亲们阅读购买说明按需选购---感谢光临] 【金皇冠信誉小米手机集市销量第一】【购买套餐送高清钢化膜+线控通话耳机+ 剪卡器(含还原卡托)+ 防辐射贴+专用高清贴膜+ 擦机布+ 耳机绕线器+手机电影支架+ 一年延保服务+ 默认享受顺丰包邮 !
 </p>
   <div id="J_TEditItem" class="tb-editor-menu"></div>
 </div>

很明显,这里面包含了两台手机,我们的目标是提取两个手机的名字出来。
 
由于当我们feed这个html到HTMLParser中后,他们所有的标签都迭代,如果需要它只提取我们需要的数据时,我们需要设置当handle_starttag遇到那个标签和属性时,才调用handle_data并print出我们的结果,这个时候我们可以使用一个flg作为判定,代码如下:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#定义一个MyParser继承自HTMLParser
class MyParser(HTMLParser):
    re=[]#放置结果
    flg=0#标志,用以标记是否找到我们需要的标签
    def handle_starttag(self, tag, attrs):
        if tag=='h3':#目标标签
            for attr in attrs:
                if attr[0]=='class' and attr[1]=='tb-main-title':#目标标签具有的属性
                    self.flg=1#符合条件则将标志设置为1
                    break
        else:
            pass
  
    def handle_data(self, data):
        if self.flg==1:
            self.re.append(data.strip())#如果标志为我们需要的标志,则将数据添加到列表中
            self.flg=0#重置标志,进行下次迭代
        else:
            pass
 
 
my=MyParser()
my.feed(html)
 
运行结果如下,达到了我们的预期:


 
上面只是HTMLParser一个非常简单的应用,但却可以反应了HTMLParser这个类的一些特质。有了这些基本的认识后,我们就可以将相关功能进行扩展,从而形成一个标准的爬虫了。下次,我们将利用相关的知识,构建一个基本的网络爬虫,敬请期待哦。
 
--------------------------------------------------
本文为作者原创文章,转摘请注明出处:@Datazen

PYTHON HTML.PARSER库学习小结--转载的更多相关文章

  1. Python html.parser库学习小结

    分类路径:/Datazen/DataMining/Crawler/   前段时间,一朋友让我做个小脚本,抓一下某C2C商城上竞争对手的销售/价格数据,好让他可以实时调整自己的营销策略.自己之前也有过写 ...

  2. python爬虫解析库学习

    一.xpath库使用: 1.基本规则: 2.将文件转为HTML对象: html = etree.parse('./test.html', etree.HTMLParser()) result = et ...

  3. Python之matplotlib库学习

    matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图.而且也可以方便地将它作为绘图控件,嵌入GUI应用程序中. 它的文档相当完备, ...

  4. python 之Requests库学习笔记

    1.    Requests库安装 Windows平台安装说明: 直接以管理员身份打开cmd运行界面,使用pip管理工具进行requests库的安装. 具体安装命令如下: >pip instal ...

  5. Python之matplotlib库学习:实现数据可视化

    1. 安装和文档 pip install matplotlib 官方文档 为了方便显示图像,还使用了ipython qtconsole方便显示.具体怎么弄网上搜一下就很多教程了. pyplot模块是提 ...

  6. 基于Windows平台的Python多线程及多进程学习小结

    python多线程及多进程对于不同平台有不同的工具(platform-specific tools),如os.fork仅在Unix上可用,而windows不可用,该文仅针对windows平台可用的工具 ...

  7. Python之Pandas库学习(二):数据读写

    1. I/O API工具 读取函数 写入函数 read_csv to_csv read_excel to_excel read_hdf to_hdf read_sql to_sql read_json ...

  8. Python之Pandas库学习(一):简介

    官方文档 1. 安装Pandas windos下cmd:pip install pandas 导入pandas包:import pandas as pd 2. Series对象 带索引的一维数组 创建 ...

  9. python的pandas库学习笔记

    导入: import pandas as pd from pandas import Series,DataFrame 1.两个主要数据结构:Series和DataFrame (1)Series是一种 ...

随机推荐

  1. ID和Name

    ID和Name都可以用来标识一个标记,Javascript分别有两个方法getElementById和getElementByName来定位Dom节点. 区别如下: 1.我们知道在网页做Post提交时 ...

  2. 【转】SVM入门(一)SVM的八股简介

    (一)SVM的八股简介 支持向量机(Support Vector Machine)是Cortes和Vapnik于1995年首先提出的,它在解决小样本.非线性及高维模式识别中表现出许多特有的优势,并能够 ...

  3. Struts2-综合项目

    综合项目:视频后台管理系统 开发环境:Tomcat6(服务器)+jdk6(windows操作系统) 使用技术:struts2(后台)+jsp(前台显示)+ajax(信息传递)+json(服务器响应前台 ...

  4. 几乎考虑到了每个细节的php图片上传

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> < ...

  5. Javascript-涨工资案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. c语言中strcpy与strlen函数对字符串最后的'\0'的处理

    对于strcpy来说,它会把字符串最后的‘\0’一起拷贝 对于strlen来说,它计算字符串长度的时候不会把最后的‘\0’计算进去

  7. Perl中的输入输出流(三)

    Perl中读取标准输入:<STDIN> foreach (<STDIN>)  { print "I saw $_";} 钻石操作符<>:它的参数 ...

  8. SQL 中【NULL】和【无】烦躁的问题

    很烦躁,烦躁的很,总结一下. 先简单的说下: NULL   : 不确定的东西 无       :没有东西 复杂的见下文....... 一 .null值 下面举个最简单的例子,平常工作当中肯定比这个sq ...

  9. MySQL从删库到跑路(四)——MySQL数据库创建实例

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.创建数据库 1.创建数据库 创建数据库,指定数据库的默认字符集为utf8.create database sch ...

  10. c++第五天:默认初始化

    1.算数类型.(整型和浮点型) 类型决定了数据所占的比特数以及该如何解释这些比特的内容. 练习2.1... 各种类型在计算机中所占的比特数不同,解释方法不同.有符号要花费一个比特存储符号,最大正值要比 ...