[python学习] 简单爬取维基百科程序语言消息盒

        文章主要讲述如何通过Python爬取维基百科的消息盒(Infobox),主要是通过正则表达式和urllib实现;后面的文章可能会讲述通过BeautifulSoup实现爬取网页知识。由于这方面的文章还是较少,希望提供一些思想和方法对大家有所帮助。如果有错误或不足之处,欢迎之处;如果你只想知道该篇文章最终代码,建议直接阅读第5部分及运行截图。

一. 维基百科和Infobox

        你可能会疑惑Infobox究竟是个什么东西呢?下面简单介绍。
        维基百科作为目前规模最大和增长最快的开放式的在线百科系统,其典型包括两个网状结构:文章网络和分类树(以树为主体的图)。该篇博客主要是对维基百科“程序语言”结构进行分析,下载网页后提取相关消息盒(Infobox)中属性和对应的值。
        Infobox是模板(一系列的信息框),通常是成对的标签label和数据data组成。参考:http://zh.wikipedia.org/wiki/Template:Infobox
        下图是维基百科“世界政区索引”中“中国”的部分Infobox信息和“程序设计语言列表”的“ACL2”语言的消息盒。

  

二. 爬虫实现

        1. python下载html网页

        首先需要访问维基百科的“程序设计语言列表”,并简单讲述如何下载静态网页的代码。在维基百科中输入如下URL可以获取所有程序语言列表:
        http://zh.wikipedia.org/wiki/程序设计语言列表

        你可以看到从A到Z的各种程序语言,如A# .NET、ActionScript、C++、易语言等,当然可能其中很多语言都没有完善或没有消息盒Infobox。同样如果你想查询世界各个国家的信息,输入URL如下:
        http://zh.wikipedia.org/wiki/世界政区索引
        通过如下代码可以获取静态的html页面:

# coding=utf-8
import urllib
import time
import re

#第一步 获取维基百科内容
#http://zh.wikipedia.org/wiki/程序设计语言列表
keyname="程序设计语言列表"
temp='http://zh.wikipedia.org/wiki/'+str(keyname)
content = urllib.urlopen(temp).read()
open('wikipedia.html','w+').write(content)
print 'Start Crawling pages!!!'

        获取的本地wikipedia.html界面如下图所示:

        2. 正则表达式获取URL超链接

        现在需要通过Python正则表达式获取所有语言的超链接URL。
        网页中创建超链接需要使用A标记符,结束标记符为</A>.它的最基本属性是href,用于指定超链接的目标,通过href属性指定不同的值,可以创建不同类型的超链接.

href = '<p><a href="www.csdn.cn" title="csdn">CSDN</a></p>'
link = re.findall(r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')", href)
print link

        上面是获取网页URL的正则表达式代码,输出结果是:['www.csdn.cn']。
        但是获取“程序设计语言列表”中所有语言时,我是通过人工确定起始位置“0-9”和结束位置“参看”进行查找的,代码如下:

# coding=utf-8
import urllib
import time
import re

#第一步 获取维基百科内容
#http://zh.wikipedia.org/wiki/程序设计语言列表
keyname="程序设计语言列表"
temp='http://zh.wikipedia.org/wiki/'+str(keyname)
content = urllib.urlopen(temp).read()
open('wikipedia.html','w+').write(content)
print 'Start Crawling pages!!!'

#第二步 获取网页中的所有URL
#从原文中"0-9"到"参看"之间是A-Z各个语言的URL
start=content.find(r'0-9')
end=content.find(r'参看')
cutcontent=content[start:end]
link_list = re.findall(r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')", cutcontent)
fileurl=open('test.txt','w')
for url in link_list:
    print url

        输出的结果HTML源码主要包括以下几种形式:

<a href="#A">A</a>
<a href="/wiki/C%EF%BC%83" title="C#" class="mw-redirect">C#</a>
<a href="/w/index.php?title=..." class="new" title="A Sharp (.NET)(页面不存在)">A# .NET</a>
输出:
#A
/wiki/C%EF%BC%83
/w/index.php?title=A%2B%2B&amp;action=edit&amp;redlink=1.

        此时获取了href中URL,很显然“http://zh.wikipedia.org”加上获取的后缀就是具体的一门语言信息,如:

        http://zh.wikipedia.org/wiki/C#

        http://zh.wikipedia.org/wiki/A_Sharp_(.NET) 

       它会转换成C%EF%..等形式。而index.php?此种形式表示该页面维基百科未完善,相应的Infobox消息盒也是不存在的。下面就是去到每一个具体的URL获取里面的title信息,同时下载相应的静态URL。

        3. 获取程序语言title信息及下载html

        首先通过拼接成完整的URL,在通过open函数下载对应的程序语言html源码至language文件夹下;再通过正则表达式r'(?<=<title>).*?(?=</title>)'可以获取网页的title信息。代码如下:

# coding=utf-8
import urllib
import time
import re

#第一步 获取维基百科内容
#http://zh.wikipedia.org/wiki/程序设计语言列表
keyname="程序设计语言列表"
temp='http://zh.wikipedia.org/wiki/'+str(keyname)
content = urllib.urlopen(temp).read()
open('wikipedia.html','w+').write(content)
print 'Start Crawling pages!!!'

#第二步 获取网页中的所有URL
#从原文中"0-9"到"参看"之间是A-Z各个语言的URL
start=content.find(r'0-9')
end=content.find(r'参看')
cutcontent=content[start:end]
link_list = re.findall(r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')", cutcontent)
fileurl=open('test.txt','w')
for url in link_list:
    #字符串包含wiki或/w/index.php则正确url 否则A-Z
    if url.find('wiki')>=0 or url.find('index.php')>=0:
        fileurl.write(url+'\n')
        #print url
        num=num+1
fileurl.close()
print 'URL Successed! ',num,' urls.'

#第三步 下载每个程序URL静态文件并获取Infobox对应table信息
#国家:http://zh.wikipedia.org/wiki/阿布哈茲
#语言:http://zh.wikipedia.org/wiki/ActionScript
info=open('infobox.txt','w')
info.write('****************获取程序语言信息*************\n\n')
j=1
for url in link_list:
    if url.find('wiki')>=0 or url.find('index.php')>=0:
        #下载静态html
        wikiurl='http://zh.wikipedia.org'+str(url)
        print wikiurl
        language = urllib.urlopen(wikiurl).read()
        name=str(j)+' language.html'
        #注意 需要创建一个country的文件夹 否则总报错No such file or directory
        open(r'language/'+name,'w+').write(language) #写方式打开+没有即创建
        #获取title信息
        title_pat=r'(?<=<title>).*?(?=</title>)'
        title_ex=re.compile(title_pat,re.M|re.S)
        title_obj=re.search(title_ex, language) #language对应当前语言HTML所有内容
        title=title_obj.group()
        #获取内容'C语言 - 维基百科,自由的百科全书' 仅获取语言名
        middle=title.find(r'-')
        info.write('【程序语言  '+title[:middle]+'】\n')
        print title[:middle]

        #设置下载数量
        j=j+1
        time.sleep(1)
        if j==20:
            break;
    else:
        print 'Error url!!!'
else:
    print 'Download over!!!'

        输出结果如下图所示,其中获取20个程序语言URL的标题输入infobox.txt如下:

        然后是获取每门语言HTML下载至本地的language文件夹下,需要自己创建一个文件夹。其中一门语言代码如下,标题就是下图左上方的ACL2:

        4. 爬取class=Infobox的table信息

        获取Infobox的table信息,通过分析源代码发现“程序设计语言列表”的消息盒如下:
        <table class="infobox vevent" ..><tr><th></th><td></td></tr></table>
        而“世界政区索引”的消息盒形式如下:
        <table class="infobox"><tr><td></td></tr></table>
        具体的代码如下所示:

# coding=utf-8
import urllib
import time
import re

#第一步 获取维基百科内容
#http://zh.wikipedia.org/wiki/程序设计语言列表
keyname="程序设计语言列表"
temp='http://zh.wikipedia.org/wiki/'+str(keyname)
content = urllib.urlopen(temp).read()
open('wikipedia.html','w+').write(content)
print 'Start Crawling pages!!!'

#第二步 获取网页中的所有URL
#从原文中"0-9"到"参看"之间是A-Z各个语言的URL
start=content.find(r'0-9')
end=content.find(r'参看')
cutcontent=content[start:end]
link_list = re.findall(r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')", cutcontent)
fileurl=open('test.txt','w')
for url in link_list:
    #字符串包含wiki或/w/index.php则正确url 否则A-Z
    if url.find('wiki')>=0 or url.find('index.php')>=0:
        fileurl.write(url+'\n')
        #print url
        num=num+1
fileurl.close()
print 'URL Successed! ',num,' urls.'

#第三步 下载每个程序URL静态文件并获取Infobox对应table信息
#国家:http://zh.wikipedia.org/wiki/阿布哈茲
#语言:http://zh.wikipedia.org/wiki/ActionScript
info=open('infobox.txt','w')
info.write('****************获取程序语言信息*************\n\n')
j=1
for url in link_list:
    if url.find('wiki')>=0 or url.find('index.php')>=0:
        #下载静态html
        wikiurl='http://zh.wikipedia.org'+str(url)
        print wikiurl
        language = urllib.urlopen(wikiurl).read()
        name=str(j)+' language.html'
        #注意 需要创建一个country的文件夹 否则总报错No such file or directory
        open(r'language/'+name,'w+').write(language) #写方式打开+没有即创建
        #获取title信息
        title_pat=r'(?<=<title>).*?(?=</title>)'
        title_ex=re.compile(title_pat,re.M|re.S)
        title_obj=re.search(title_ex, language) #language对应当前语言HTML所有内容
        title=title_obj.group()
        #获取内容'C语言 - 维基百科,自由的百科全书' 仅获取语言名
        middle=title.find(r'-')
        info.write('【程序语言  '+title[:middle]+'】\n')
        print title[:middle]

        #第四步 获取Infobox的内容
        #标准方法是通过<table>匹配</table>确认其内容,找与它最近的一个结束符号
        #但此处分析源码后取巧<p><b>实现
        start=language.find(r'<table class="infobox vevent"') #起点记录查询位置
        end=language.find(r'<p><b>'+title[:middle-1])    #减去1个空格
        infobox=language[start:end]
        print infobox

        #设置下载数量
        j=j+1
        time.sleep(1)
        if j==20:
            break;
    else:
        print 'Error url!!!'
else:
    print 'Download over!!!'

        “print infobox”输出其中一门语言ActionScript的InfoBox消息盒部分源代码如下:

<table class="infobox vevent" cellspacing="3" style="border-spacing:3px;width:22em;text-align:left;font-size:small;line-height:1.5em;">
<caption class="summary"><b>ActionScript</b></caption>
<tr>
<th scope="row" style="text-align:left;white-space:nowrap;;;">发行时间</th>
<td style=";;">1998年</td>
</tr>
<tr>
<th scope="row" style="text-align:left;white-space:nowrap;;;">实现者</th>
<td class="organiser" style=";;"><a href="/wiki/Adobe_Systems" title="Adobe Systems">Adobe Systems</a></td>
</tr>
<tr>
<tr>
<th scope="row" style="text-align:left;white-space:nowrap;;;">启发语言</th>
<td style=";;"><a href="/wiki/JavaScript" title="JavaScript">JavaScript</a>、<a href="/wiki/Java" title="Java">Java</a></td>
</tr>
</table> 

        5. 爬取消息盒属性-属性值

        爬取格式如下:
        <table>
                <tr>
                      <th>属性</th>
                      <td></td>
                </tr>
        </table>
        其中th表示加粗处理,td和th中可能存在属性如title、id、type等值;同时<td></td>之间的内容可能存在<a href=..></a>或<span></span>或<br />等值,都需要处理。下面先讲解正则表达式获取td值的例子:
        参考:http://bbs.csdn.net/topics/390353859?page=1

<table>
<tr>
<td>序列号</td><td>DEIN3-39CD3-2093J3</td>
<td>日期</td><td>2013年1月22日</td>
<td>售价</td><td>392.70 元</td>
<td>说明</td><td>仅限5用户使用</td>
</tr>
</table>

        Python代码如下:

s = '''<table>
....
</table>''' #对应上面HTML
res = r'<td>(.*?)</td><td>(.*?)</td>'
m = re.findall(res,s,re.S|re.M)
for line in m:
    print unicode(line[0],'utf-8'),unicode(line[1],'utf-8') #unicode防止乱码

#输出结果如下:
#序列号 DEIN3-39CD3-2093J3
#日期 2013年1月22日
#售价 392.70 元
#说明 仅限5用户使用

       
如果<td id="">包含该属性则正则表达式为r'<td id=.*?>(.*?)</td>';同样如果不一定是id属性开头,则可以使用正则表达式r'<td .*?>(.*?)</td>'。
        最终代码如下:

# coding=utf-8
import urllib
import time
import re

#第一步 获取维基百科内容
#http://zh.wikipedia.org/wiki/程序设计语言列表
keyname="程序设计语言列表"
temp='http://zh.wikipedia.org/wiki/'+str(keyname)
content = urllib.urlopen(temp).read()
open('wikipedia.html','w+').write(content)
print 'Start Crawling pages!!!'

#第二步 获取网页中的所有URL
#从原文中"0-9"到"参看"之间是A-Z各个语言的URL
start=content.find(r'0-9')
end=content.find(r'参看')
cutcontent=content[start:end]
link_list = re.findall(r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')", cutcontent)
fileurl=open('test.txt','w')
for url in link_list:
    #字符串包含wiki或/w/index.php则正确url 否则A-Z
    if url.find('wiki')>=0 or url.find('index.php')>=0:
        fileurl.write(url+'\n')
        #print url
        num=num+1
fileurl.close()
print 'URL Successed! ',num,' urls.'

#第三步 下载每个程序URL静态文件并获取Infobox对应table信息
#国家:http://zh.wikipedia.org/wiki/阿布哈茲
#语言:http://zh.wikipedia.org/wiki/ActionScript
info=open('infobox.txt','w')
info.write('****************获取程序语言信息*************\n\n')
j=1
for url in link_list:
    if url.find('wiki')>=0 or url.find('index.php')>=0:
        #下载静态html
        wikiurl='http://zh.wikipedia.org'+str(url)
        print wikiurl
        language = urllib.urlopen(wikiurl).read()
        name=str(j)+' language.html'
        #注意 需要创建一个country的文件夹 否则总报错No such file or directory
        open(r'language/'+name,'w+').write(language) #写方式打开+没有即创建
        #获取title信息
        title_pat=r'(?<=<title>).*?(?=</title>)'
        title_ex=re.compile(title_pat,re.M|re.S)
        title_obj=re.search(title_ex, language) #language对应当前语言HTML所有内容
        title=title_obj.group()
        #获取内容'C语言 - 维基百科,自由的百科全书' 仅获取语言名
        middle=title.find(r'-')
        info.write('【程序语言  '+title[:middle]+'】\n')
        print title[:middle]

        #第四步 获取Infobox的内容
        #标准方法是通过<table>匹配</table>确认其内容,找与它最近的一个结束符号
        #但此处分析源码后取巧<p><b>实现
        start=language.find(r'<table class="infobox vevent"') #起点记录查询位置
        end=language.find(r'<p><b>'+title[:middle-1])    #减去1个空格
        infobox=language[start:end]
        #print infobox

        #第五步 获取table中属性-属性值
        if "infobox vevent" in language: #防止无Infobox输出多余换行
            #获取table中tr值
            res_tr = r'<tr>(.*?)</tr>'
            m_tr =  re.findall(res_tr,infobox,re.S|re.M)
            for line in m_tr:
                #print unicode(line,'utf-8')

                #获取表格第一列th 属性
                res_th = r'<th scope=.*?>(.*?)</th>'
                m_th = re.findall(res_th,line,re.S|re.M)
                for mm in m_th:
                    #如果获取加粗的th中含超链接则处理
                    if "href" in mm:
                        restr = r'<a href=.*?>(.*?)</a>'
                        h = re.findall(restr,mm,re.S|re.M)
                        print unicode(h[0],'utf-8')
                        info.write(h[0]+'\n')
                    else:
                        #报错用str()不行 针对两个类型相同的变量
                        #TypeError: coercing to Unicode: need string or buffer, list found
                        print unicode(mm,'utf-8') #unicode防止乱
                        info.write(mm+'\n')

                #获取表格第二列td 属性值
                res_td = r'<td .*?>(.*?)</td>'
                m_td = re.findall(res_td,line,re.S|re.M)
                for nn in m_td:
                    if "href" in nn:
                        #处理超链接<a href=../rel=..></a>
                        res_value = r'<a .*?>(.*?)</a>'
                        m_value = re.findall(res_value,nn,re.S|re.M) #m_td会出现TypeError: expected string or buffer
                        for value in m_value:
                            print unicode(value,'utf-8'),
                            info.write(value+' ')
                        print ' ' #换行
                        info.write('\n')
                    else:
                        print unicode(nn,'utf-8')
                        info.write(nn+'\n')
            print '\n'
            info.write('\n\n')
        else:
            print 'No Infobox\n'
            info.write('No Infobox\n\n\n')

        #设置下载数量
        j=j+1
        time.sleep(1)
        if j==40:
            break;
    else:
        print 'Error url!!!'
else:
    print 'Download over!!!'

        输出结果是自定义爬取多少门语言,其中Ada编程语言如下图所示:

        最初我采用的是如下方法,维基百科需要中文繁体,需要人工标注分析HTML再爬取两个尖括号(>...<)之间的内容:

#启发语言
start=infobox.find(r'啟發語言')
end=infobox.find(r'</tr>',start)
print infobox[start:end]
info.write(infobox[start:end]+'\n') 

        当然代码中还存在很多小问题,比如爬取的信息中含<a href>超链接时只能爬取含超链接的信息,而没有超链接的信息被忽略了;如何删除<span class="noprint"></span>或<br />等信息。但是我希望自己能提供一种爬取网页知识的方法给大家分享,后面可能会讲述如何通过Python实现BeautifulSoup爬取网页知识以及如何爬取图片,很多时候我们在野网站浏览图片都需要不断点击下一张。
       (By:Eastmount 2015-3-18 深夜4点  http://blog.csdn.net/eastmount/

时间: 2024-10-29 05:18:11

[python学习] 简单爬取维基百科程序语言消息盒的相关文章

[Python学习] 简单爬取CSDN下载资源信息

        这是一篇Python爬取CSDN下载资源信息的例子,主要是通过urllib2获取CSDN某个人所有资源的资源URL.资源名称.下载次数.分数等信息:写这篇文章的原因是我想获取自己的资源所有的评论信息,但是由于评论采用JS临时加载,所以这篇文章先简单介绍如何人工分析HTML页面爬取信息. 源代码 # coding=utf-8 import urllib import time import re import os #********************************

[python] lantern访问中文维基百科及selenium爬取维基百科语料

希望文章对你有所帮助,尤其是web爬虫初学者和NLP相关同学.当然你也能,懂的~ 目录: 0 前言 1 lantern访问中文维基百科 2 Selenium调用Chrome自动访问维基百科 3 Selenium爬取维基百科信息 代码及软件下载地址:http://download.csdn.net/detail/eastmount/9422875 0 前言 在对海量知识挖掘和自然语言处理(Natural Language Processing,简称NLP)中会大量涉及到三大百科的语料问题,尤其是中

[python学习] 简单爬取图片网站图库中图片

        最近老师让学习Python与维基百科相关的知识,无聊之中用Python简单做了个爬取"游讯网图库"中的图片,因为每次点击下一张感觉非常浪费时间又繁琐.主要分享的是如何爬取HTML的知识和Python如何下载图片:希望对大家有所帮助,同时发现该网站的图片都挺精美的,建议阅读原网下载图片,支持游讯网不要去破坏它.         通过浏览游讯网发现它的图库URL为,其中全部图片为0_0_1到0_0_75:         http://pic.yxdown.com/list

Node.js环境下编写爬虫爬取维基百科内容的实例分享_node.js

基本思路思路一(origin:master):从维基百科的某个分类(比如:航空母舰(key))页面开始,找出链接的title属性中包含key(航空母舰)的所有目标,加入到待抓取队列中.这样,抓一个页面的代码及其图片的同时,也获取这个网页上所有与key相关的其它网页的地址,采取一个类广度优先遍历的算法来完成此任务. 思路二(origin:cat):按分类进行抓取.注意到,维基百科上,分类都以Category:开头,由于维基百科有很好的文档结构,很容易从任一个分类,开始,一直把其下的所有分类全都抓取

[python] 常用正则表达式爬取网页信息及分析HTML标签总结

这篇文章主要是介绍Python爬取网页信息时,经常使用的正则表达式及方法.它是一篇总结性文章,实用性比较大,主要解决自己遇到的爬虫问题,也希望对你有所帮助~ 当然如果会Selenium基于自动化测试爬虫.BeautifulSoup分析网页DOM节点,这就更方便了,但本文更多的是介绍基于正则的底层爬取分析. 涉及内容如下: 常用正则表达式爬取网页信息及HTML分析总结 1.获取<tr></tr>标签之间内容 2.获取<a href..></a>超链接之间内容

[Python学习] 简单网络爬虫抓取博客文章及思想介绍

        前面一直强调Python运用到网络爬虫方面非常有效,这篇文章也是结合学习的Python视频知识及我研究生数据挖掘方向的知识.从而简单介绍下Python是如何爬去网络数据的,文章知识非常简单,但是也分享给大家,就当简单入门吧!同时只分享知识,希望大家不要去做破坏网络的知识或侵犯别人的原创型文章.主要包括:         1.介绍爬取CSDN自己博客文章的简单思想及过程         2.实现Python源码爬取新浪韩寒博客的316篇文章 一.爬虫的简单思想      最近看刘兵

教你用python3根据关键词爬取百度百科的内容_python

前言 关于python版本,我一开始看很多资料说python2比较好,因为很多库还不支持3,但是使用到现在为止觉得还是pythin3比较好用,因为编码什么的问题,觉得2还是没有3方便.而且在网上找到的2中的一些资料稍微改一下也还是可以用. 好了,开始说爬百度百科的事. 这里设定的需求是爬取北京地区n个景点的全部信息,n个景点的名称是在文件中给出的.没有用到api,只是单纯的爬网页信息.  1.根据关键字获取url 由于只需要爬取信息,而且不涉及交互,可以使用简单的方法而不需要模拟浏览器. 可以直

使用Python多线程爬虫爬取电影天堂资源_python

最近花些时间学习了一下Python,并写了一个多线程的爬虫程序来获取电影天堂上资源的迅雷下载地址,代码已经上传到GitHub上了,需要的同学可以自行下载.刚开始学习python希望可以获得宝贵的意见. 先来简单介绍一下,网络爬虫的基本实现原理吧.一个爬虫首先要给它一个起点,所以需要精心选取一些URL作为起点,然后我们的爬虫从这些起点出发,抓取并解析所抓取到的页面,将所需要的信息提取出来,同时获得的新的URL插入到队列中作为下一次爬取的起点.这样不断地循环,一直到获得你想得到的所有的信息爬虫的任务

[python爬虫] Selenium爬取新浪微博内容及用户信息

在进行自然语言处理.文本分类聚类.推荐系统.舆情分析等研究中,通常需要使用新浪微博的数据作为语料,这篇文章主要介绍如果使用Python和Selenium爬取自定义新浪微博语料.因为网上完整的语料比较少,而使用Selenium方法有点简单.速度也比较慢,但方法可行,同时能够输入验证码.希望文章对你有所帮助~ 爬取结果 首先可以爬取用户ID.用户名.微博数.粉丝数.关注数及微博信息.其中微博信息包括转发或原创.点赞数.转发数.评论数.发布时间.微博内容等等.如下图所示: 同时也可以爬取微博的众多用户