• UID11822
  • 登录2017-07-17
  • 粉丝2
  • 关注0
  • 发帖31
  • 主页http://www.gooseeker.com/
  • 金币214枚
社区居民
原创写手
fullerhua 发布于2016-05-19 11:45
0/914

Python使用xslt提取网页数据

楼层直达
1,引言
在Python网络爬虫内容提取器一文我们详细讲解了核心部件:可插拔的内容提取器类gsExtractor。本文记录了确定gsExtractor的技术路线过程中所做的编程实验。这是第一部分,实验了用xslt方式一次性提取静态网页内容并转换成xml格式。

2,用lxml库实现网页内容提取
lxml是python的一个库,可以迅速、灵活地处理 XML。它支持 XML Path Language (XPath) 和 Extensible Stylesheet Language Transformation (XSLT),并且实现了常见的 ElementTree API。
这2天测试了在python中通过xslt来提取网页内容,记录如下:
2.1,抓取目标
假设要提取集搜客官网旧版论坛的帖子标题和回复数,如下图,要把整个列表提取出来,存成xml格式


2.2,源代码1:只抓当前页,结果显示在控制台
Python的优势是用很少量代码就能解决一个问题,请注意下面的代码看起来很长,其实python函数调用没有几个,大篇幅被一个xslt脚本占去了,在这段代码中,只是一个好长的字符串而已,至于为什么选择xslt,而不是离散的xpath或者让人挠头的正则表达式,请参看Python即时网络爬虫项目启动说明,我们期望通过这个架构,把程序员的时间节省下来一大半。
可以拷贝运行下面的代码(在windows10, python3.2下测试通过):
from urllib import request
from lxml import etree
url="http://www.gooseeker.com/cn/forum/7"
conn = request.urlopen(url)
     
doc = etree.HTML(conn.read())
     
xslt_root = etree.XML("""\
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<列表>
<xsl:apply-templates select="//*[@id='forum' and count(./table/tbody/tr[position()>=1 and count(.//*[@class='topic']/a/text())>0])>0]" mode="列表"/>
</列表>
</xsl:template>
     
     
     
<xsl:template match="table/tbody/tr[position()>=1]" mode="list">
<item>
<标题>
<xsl:value-of select="*//*[@class='topic']/a/text()"/>
<xsl:value-of select="*[@class='topic']/a/text()"/>
<xsl:if test="@class='topic'">
<xsl:value-of select="a/text()"/>
</xsl:if>
</标题>
<回复数>
<xsl:value-of select="*//*[@class='replies']/text()"/>
<xsl:value-of select="*[@class='replies']/text()"/>
<xsl:if test="@class='replies'">
<xsl:value-of select="text()"/>
</xsl:if>
</回复数>
</item>
</xsl:template>
     
<xsl:template match="//*[@id='forum' and count(./table/tbody/tr[position()>=1 and count(.//*[@class='topic']/a/text())>0])>0]" mode="列表">
<item>
<list>
<xsl:apply-templates select="table/tbody/tr[position()>=1]" mode="list"/>
</list>
</item>
</xsl:template>
</xsl:stylesheet>""")
     
transform = etree.XSLT(xslt_root)
result_tree = transform(doc)
print(result_tree)
2.3,抓取结果
得到的抓取结果如下图:

2.4,源代码2:翻页抓取,结果存入文件

我们对2.2的代码再做进一步修改,增加翻页抓取和存结果文件功能,代码如下:
from urllib import request
from lxml import etree
import time
     
xslt_root = etree.XML("""\
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<列表>
<xsl:apply-templates select="//*[@id='forum' and count(./table/tbody/tr[position()>=1 and count(.//*[@class='topic']/a/text())>0])>0]" mode="列表"/>
</列表>
</xsl:template>
     
     
     
<xsl:template match="table/tbody/tr[position()>=1]" mode="list">
<item>
<标题>
<xsl:value-of select="*//*[@class='topic']/a/text()"/>
<xsl:value-of select="*[@class='topic']/a/text()"/>
<xsl:if test="@class='topic'">
<xsl:value-of select="a/text()"/>
</xsl:if>
</标题>
<回复数>
<xsl:value-of select="*//*[@class='replies']/text()"/>
<xsl:value-of select="*[@class='replies']/text()"/>
<xsl:if test="@class='replies'">
<xsl:value-of select="text()"/>
</xsl:if>
</回复数>
</item>
</xsl:template>
     
<xsl:template match="//*[@id='forum' and count(./table/tbody/tr[position()>=1 and count(.//*[@class='topic']/a/text())>0])>0]" mode="列表">
<item>
<list>
<xsl:apply-templates select="table/tbody/tr[position()>=1]" mode="list"/>
</list>
</item>
</xsl:template>
</xsl:stylesheet>""")
     
baseurl = "http://www.gooseeker.com/cn/forum/7"
basefilebegin = "jsk_bbs_"
basefileend = ".xml"
count = 1
while (count < 12):
        url = baseurl + "?page=" + str(count)
        conn = request.urlopen(url)
        doc = etree.HTML(conn.read())
        transform = etree.XSLT(xslt_root)
        result_tree = transform(doc)
        print(str(result_tree))
        file_obj = open(basefilebegin+str(count)+basefileend,'w',encoding='UTF-8')
        file_obj.write(str(result_tree))
        file_obj.close()
        count += 1
        time.sleep(2)
我们增加了写文件的代码,还增加了一个循环,构造每个翻页的网址,但是,如果翻页过程中网址总是不变怎么办?其实这就是动态网页内容,下面会讨论这个问题。

3,总结
这是开源Python通用爬虫项目的验证过程,在一个爬虫框架里面,其它部分都容易做成通用的,就是网页内容提取和转换成结构化的操作难于通用,我们称之为提取器。但是,借助GooSeeker可视化提取规则生成器MS谋数台,提取器的生成过程将变得很便捷,而且可以标准化插入,从而实现通用爬虫,在后续的文章中会专门讲解MS谋数台与Python配合的具体方法。

4,接下来阅读

本文介绍的方法通常用来抓取静态网页内容,也就是所谓的html文档中的内容,目前很多网站内容是用javascript动态生成的,一开始html是没有这些内容的,通过后加载方式添加进来,那么就需要采用动态技术,请阅读Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容


5,集搜客GooSeeker开源代码下载源
1. GooSeeker开源Python网络爬虫GitHub源

5,文档修改历史
2016-05-26:V2.0,增补文字说明;把跟帖的代码补充了进来
2016-05-29:V2.1,增加最后一章源代码下载源
[fullerhua于2016-05-30 11:10编辑了帖子]

0人打赏
您需要登录后才可以回帖
发表回复
极贡献
技术问答
专题荟萃
程序人生
视觉设计
Android开发
iOS开发
编程语言
前端开发
后端开发
服务器架构
软件测试
运维方案
创业路上



最热文章墙

  • 77037/375   【精品推荐】200多种Android动画效果的强悍框架,太全了,不看这个,再有动画的问题,不理你了^@^

  • 44087/191   情人节福利,程序员表白的正确姿势:改几行代码就变成自己的表白了

  • 43710/0   Python爬虫:常用浏览器的useragent

  • 40229/259   【精品推荐】Android版产品级的音乐播放器源码,功能太强大了,最好的产品原型有木有?

  • 37959/145   省时省力的Android组件群来了,非常棒的原型参考

  • 29226/142   2016抢红包软件及源码

  • 28978/2   超全!整理常用的iOS第三方资源

  • 28850/71   原创表白APP,以程序员的姿势备战新年后的7夕,持续完善中!

  • 23573/159   Android版类似UC浏览器:非常赞,产品级的源码

  • 22589/30   麻省理工的一帮疯子,真的实现了随意操控万物!(绝对黑科技)

  • 22273/25   Android工程师面试题大全

  • 22148/27   2016程序员跳槽全攻略

  • 21740/9   GitHub上排名前50的iOS项目:总有一款你用得着

  • 20703/20   码魂:程序员的牛B漫画

  • 18795/10   2016年最全的Android面试考题+答案 精编版

  • 18647/85   Android小而全的博客源码:非常适合全面掌握开发技巧

  • 18530/3   吐槽那些程序员的搞笑牛逼注释

  • 18524/42   一个绚丽的loading动效分析与实现!

  • 18504/73   【持续更新中】Android福利贴(二):资料源码大放送

  • 17454/1   iOS 动画总结

  • 17302/45   惊艳的App引导页:背景图片切换加各个页面动画效果

  • 17103/81   仿京东商城客户端Android最新版,不错的原型和学习资料

  • 16930/104   Android带弹幕的视频播放器源码,来自大名鼎鼎的Bilibili弹幕网站

  • 16842/23   个人收集的Android 各类功能源代码

  • 16330/5   新一代Android渠道打包工具:1000个渠道包只需要5秒

  • 16249/10   女程序员的梦,众网友的神回复

  • 16242/21   Android福利第三波【Android电子书】

  • 16111/53   基于瀑布流的美女图片浏览App,有注释的源代码

  • 16086/17   用JavaScript 来开发iOS和Android 原生应用:React Native开源框架中文版来啦

  • 16005/81   【精品推荐】类似360安全卫士安Android源码:非常赞的产品原型

  • 15939/11   年会上现场review代码是怎么样的体验!

  • 15750/23   珍藏多年的素材,灵感搜寻网站

  • 15748/0   iOS中文版资源库,非常全

  • 15048/18   65条最常用正则表达式,你要的都在这里了

  • 14575/15   基于Android支付宝支付设计和开发方案

  • 13999/17   什么是真正的黑客:收获12200+Stars,人气远超微软开源VS

  • 13972/11   有木有这样一张酷图帮你集齐所有git命令超实用

  • 13658/46   在线音乐播放器完整版(商用级的源码):非常赞,可听免费高品质专辑

  • 13483/0   GitHub iOS 库和框架Top100 

  • 13333/7   一张图搞定iOS学习路线,非常全面

  • 13326/7   用程序员的姿势抢过年的火车票

  • 13202/61   【技巧一】搭配Android Studio,如何实现App远程真机debug?

  • 12958/10   成为Java顶尖程序员 ,看这11本书就够了

  • 12877/10   微信支付终于成功了(安卓,iOS),在此分享

  • 12801/18   一张图搞定Android学习路线,非常全面

  • 12542/29   【持续更新中】Android福利贴(一):资料源码

  • 12477/3   基于Node.js的强大爬虫,能直接发布抓取的文章哦

  • 12188/4   46 个非常有用的 PHP 代码片段

  • 11744/3   即时通信第三方库

  • 11257/8   流媒体视频直播方案

  • 11172/18   八个最优秀的Android Studio插件

  • 11054/9   B站建开源工作组:APP想支持炫酷弹幕的看过来

  • 10884/9   烧了5亿美金,这家神秘的公司即将颠覆人类未来!

  • 10785/2   【精品推荐】高质量PHP代码的50个实用技巧:非常值得收藏

  • 10696/10   中国黑客的隐秘江湖:攻守对立,顶尖高手月入千万美元

  • 10059/6   开箱即用!Android四款系统架构工具

  • 9878/10   十大技巧快速提升Android应用开发性能

  • 9799/3   10款GitHub上最火爆的国产开源项目——可以媲美西半球

  • 9698/1   Android性能优化视频,文档以及工具

  • 9660/3   一张图看清Linux 内核运行原理

  • 返回顶部