最新消息:VPS服务器又从fzhost.net换回Linode了,主题仍用朋友推荐的大前端D8

【教程】抓取网并提取网页中所需要的信息 之 Python版

Python crifan 4966浏览 0评论

在通过:

【整理】关于抓取网页,分析网页内容,模拟登陆网站的逻辑/流程和注意事项

了解了抓取网页的一般流程之后,加上之前介绍的:

【总结】浏览器中的开发人员工具(IE9的F12和Chrome的Ctrl+Shift+I)-网页分析的利器

应该就很清楚如何利用工具去抓取网页,并分析源码,获得所需内容了。

下面,就来通过实际的例子来介绍,如何通过Python语言,实现这个抓取网页并提取所需内容的过程:


假设我们的需求是,从我(crifan)的Songtaste上的页面:

http://www.songtaste.com/user/351979/

先抓取网页的html源码,然后再提取其中我的songtaste上面的名字:crifan

此任务,很简单。

下面就来说说,如何用Python来实现。

 

先去写出,如何利用Python中相关的库,获得网页的html源码的代码:

#---------------------------------import---------------------------------------
import urllib2;

#------------------------------------------------------------------------------
def main():
    userMainUrl = "http://www.songtaste.com/user/351979/";
    req = urllib2.Request(userMainUrl);
    resp = urllib2.urlopen(req);
    respHtml = resp.read();
    print "respHtml=",respHtml; # you should see the ouput html

###############################################################################
if __name__=="__main__":
    main();

如此,你使用此python脚本,就可以获得最基本的,对应该url返回的html代码了。

此html源码,和你用浏览器打开:

http://www.songtaste.com/user/351979/

然后查看网页源码后,所看到的源码是一样的。

 

而我们此处想要从此html中提取出:

<div class="icon_col">
        <h1 class="h1user">crifan</h1>
...
 </div>

中的字符串:crifan

 

而之前也在

【整理】关于抓取网页,分析网页内容,模拟登陆网站的逻辑/流程和注意事项

中说过了,对于提取这样的内容的话,至少有两种常见方法。

一种是用正则表达式,即python中的re模块;

另一种是用Python的第三方库,BeautifulSoup,去帮助转换为soup对象,然后利用其内置函数,方便的帮我提取出需要的内容。

 

此处,先说第一种,用python的re来实现提取所需字符串:

#---------------------------------import---------------------------------------
import urllib2;
import re;

#------------------------------------------------------------------------------
def main():
    userMainUrl = "http://www.songtaste.com/user/351979/";
    req = urllib2.Request(userMainUrl);
    resp = urllib2.urlopen(req);
    respHtml = resp.read();
    print "respHtml=",respHtml; # you should see the ouput html
    #<h1 class="h1user">crifan</h1>
    foundH1user = re.search('<h1\s+?class="h1user">(?P<h1user>.+?)</h1>', respHtml);
    print "foundH1user=",foundH1user;
    if(foundH1user):
        h1user = foundH1user.group("h1user");
        print "h1user=",h1user;

###############################################################################
if __name__=="__main__":
    main();

如此,就可以打印出我们所需要的字符串:crifan,了。

 

注意:

而关于此处,还需注意,你自己所要处理的网站的html源码所用的charset是什么,不了解的话,可参考:

【整理】关于HTML网页源码的字符编码(charset)格式(GB2312,GBK,UTF-8,ISO8859-1等)的解释

去找到你自己所需处理的html的charset。

 

接着,再简单介绍一下,如何利用BeautifulSoup来实现提取所需字符串:

首先,需要下载对应的BeautifulSoup,此处由于Python使用的2.7版本,所以需要去

http://www.crummy.com/software/BeautifulSoup/bs3/download/3.x/

下载对应的

BeautifulSoup-3.0.6.py

下载后,将BeautifulSoup-3.0.6.py改名为BeautifulSoup.py,放到你当前python脚本同目录即可。

然后使用如下脚本:

    songtasteHtmlEncoding = "GB2312";
    soup = BeautifulSoup(respHtml, fromEncoding=songtasteHtmlEncoding);
    #<h1 class="h1user">crifan</h1>
    foundClassH1user = soup.find(attrs={"class":"h1user"});
    print "foundClassH1user=%s",foundClassH1user;
    if(foundClassH1user):
        h1userStr = foundClassH1user.string;
        print "h1userStr=",h1userStr;

则同样也可以把所需的crifan字符串提取出来。

 

对应的,完整的python源码为:

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
【版本信息】
版本:     v1.0
作者:     crifan

【详细信息】
用于:
【教程】抓取网并网页中所需要的信息 之 Python版 
https://www.crifan.com/crawl_website_html_and_extract_info_using_python/
的示例代码。

-------------------------------------------------------------------------------
"""

#---------------------------------import---------------------------------------
import urllib2;
import re;
from BeautifulSoup import BeautifulSoup;

#------------------------------------------------------------------------------
def main():
    userMainUrl = "http://www.songtaste.com/user/351979/";
    req = urllib2.Request(userMainUrl);
    resp = urllib2.urlopen(req);
    respHtml = resp.read();
    #print "respHtml=",respHtml; # you should see the ouput html

    print "Method 1: Use python re to extract info from html";
    #<h1 class="h1user">crifan</h1>
    foundH1user = re.search('<h1\s+?class="h1user">(?P<h1user>.+?)</h1>', respHtml);
    print "foundH1user=",foundH1user;
    if(foundH1user):
        h1user = foundH1user.group("h1user");
        print "h1user=",h1user;

    print "Method 2: Use python third lib BeautifulSoup to extract info from html";
    songtasteHtmlEncoding = "GB2312";
    soup = BeautifulSoup(respHtml, fromEncoding=songtasteHtmlEncoding);
    #<h1 class="h1user">crifan</h1>
    foundClassH1user = soup.find(attrs={"class":"h1user"});
    print "foundClassH1user=%s",foundClassH1user;
    if(foundClassH1user):
        h1userStr = foundClassH1user.string;
        print "h1userStr=",h1userStr;

###############################################################################
if __name__=="__main__":
    main();

 

同理,此处之所以用GB2312的原因,参见:

【整理】关于HTML网页源码的字符编码(charset)格式(GB2312,GBK,UTF-8,ISO8859-1等)的解释

 

顺便,也把整个代码,提供下载吧:

crawlWebsiteAndExtractInfo_python_2012-10-28.7z

 

额外说明:

1.其中关于如何学习和使用Python中的正则表达式的话,不熟悉的可以参考:

正则表达式学习心得

以及其中的:

Python中的正则表达式re模块的学习心得

2. 和此处相关的更多代码,可以去:

http://code.google.com/p/recsongtastemusic/source/browse/trunk

看其中的代码。

3. 而前面的,用于获得网页的源码的部分,其实我已经封装了个,功能更加全面的函数:

获得Url返回的HTML网页(源码)内容:getUrlRespHtml

相关的源代码:crifanLib.py,可以去这里下载:

http://code.google.com/p/crifanlib/

 


相关帖子:

【教程】抓取网并提取网页中所需要的信息 之 C#版

【教程】模拟登陆网站 之 Python版(内含两种版本的完整的可运行的代码)

【教程】模拟登陆网站 之 C#版(内含两种版本的完整的可运行的代码)

转载请注明:在路上 » 【教程】抓取网并提取网页中所需要的信息 之 Python版

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (22)

  1. 你好,我想问,怎么通过python抓取多个新闻网站对某关键字使用出现的次数? 我用了re,beautifulsoup模块,但只能抓取一个页面关键字出现的次数,不知如果同时抓取多个网站某关键字出现的次数。您能否帮我写个例子,抓取多个网站某关键字出现的次数?谢谢??
    焦焦2年前 (2016-11-20)回复
  2. 博主,你好!向您请教个问题呗。我的IDE是PyCharm,装的是Python2.7.9,用spynner解析的页面,应该显示中文字符的地方都是???该怎么解决啊,我试了好几种办法都不行。示例代码如下: #! /usr/bin/python #-*-coding: utf-8 -*- #coding="utf-8" import spynner browser = spynner.Browser() #创建一个浏览器对象 browser.hide() #打开浏览器,并隐藏。 browser.load("http://papers.cnki.net/shipeijun56") html = browser.html.encode("utf-8") #browser 类中有一个成员是html,是页面进过处理后的源码的字符串. #将其转码为UTF-8编码 print html browser.close() #关闭该浏览器
    赵志峰4年前 (2015-04-22)回复
  3. 请问我想要截取的数据是公式计算出来的怎么办。比如我本来想要截取网页上的一个数字,但是这个数字在源码中是用公式表示的,我只看到公式,无法得到数据怎么办
    Turmud4年前 (2015-03-26)回复
    • 那只能:想办法,分析网页的逻辑,搞懂如何公式是如何计算的,然后用代码模拟运行该公式算出你要的值。
      crifan4年前 (2015-03-27)回复
  4. 文章很好,只是本人遇到一个问题:本人想通过抓取淘宝某个产品的“评价详情”里面同一个账号评价的次数来确定这个卖家是否刷信誉,现在的问题是,“评价详情”点击之后网页发生了内部跳转,url为原来的淘宝网址加上#reviews,而我通过urlib2捕捉到的网页是之前没跳转的网页,然而用谷歌浏览器的"审查元素"可以定位某个评价用户的源码的,这是什么情况呢?求教
    求教5年前 (2013-10-04)回复
  5. 真垃圾啊 一个爬动态网站的例子都没用 还显摆个屁 有本事你把 详情里面的URL取出来 我就算你能 http://caipiao.taobao.com/lottery/order/united_hall.htm?spm=0.0.0.0.Yw9IPX
    小宝5年前 (2013-08-02)回复
    • 1.我这个不是显摆,只是给,比我更不熟悉的人,写点解释而已。 2.我的能与不能,无需他人评价,我自己知道,我能不能,就行了。所以,对于你的评论,目前态度是,不予理睬。
      crifan5年前 (2013-08-02)回复
      • 大神对这种蛆,别放在心里,网上这种人我见多了。。整天刷存在感
        一个还在摸爬滚打的IT2年前 (2016-07-18)回复
  6. 第二种方法有错啊,无法返回h1userStr
    崖上迎风雨5年前 (2013-06-26)回复
  7. 相当好用的教程,感谢分享.
    babysafe6年前 (2012-12-07)回复
  8. 请问是在什么环境上运行的?「我的电脑」?
    easoncxz6年前 (2012-11-24)回复
    • win7的cmd中,运行的python脚本。 貌似你对python完全没接触过。 所以,请自己去看: 【整理】如何学习Python + 如何有效利用Python有关的网络资源 + 如何利用Python自带手册(Python Manual) 去参考里面提到的《Dive into Python》,看最开始的关于如何运行python脚本的部分的内容即可。 然后,其中不要搞混了Python的command line和windows的cmd: 如何在Windows环境下使用Python脚本
      crifan6年前 (2012-11-24)回复
      • 啊,就是本地的意思啊。python interactive shell我是在自己的windows里试过的;我只是怀疑是不是什么GAE或者别的约定俗成的环境。那么文中的做法在GAE上实施会怎样?
        easoncxz6年前 (2012-11-24)回复
        • 哎,既然你都是开发人员了,为啥还会问 是不是在 我的电脑 中运行python脚本 这样的问题呢? 即便要问,也是问: 是不是在 当前PC(windows的cmd之类的) 中运行python脚本 类似的问题才对啊。。。。 对于gae: 暂不清楚,估计是行不通。 原因是: 我还真是本来打算去试试把此脚本弄上去试试的。 只是暂时还没去弄。 但是后来看到了相关的介绍,gae中的python,和我们本地(安装的标准的)python不同,很多网络相关的库,都是有变动的,所以,我现在的脚本,如果直接拿到gae上运行,估计也运行不了,即使能运行,估计也有会很多兼容性问题。 到时候,如果还要我在去为了gae专门调试,再该代码,则代价太大,暂不会考虑这条路的。
          crifan6年前 (2012-11-24)回复
  9. 您好。我想实现的功能看起来很简单, 就是类似httpwatch的network瀑布图那样(ie9的F12功能类似network-timing) 可以得到一个网页的全部内容的下载信息(url,下载的时间) 包括外链、图片、flash、音频等。 因为很多内容不是在框架的html源码中,通过正则分析可以得到的。 而是需要在客户端的浏览器中,通过js解析以后得到的。 所以一直没有好的思路。 在windows下,试过通过httpwatch和fiddler的接口实现, 在linux上,试过通过pyqt的webbowser控件实现,但是感觉都不是很理想。 想看看python是否有什么其他的思路来实现? 象获取博客内容这样属于目标比较明确的需求,可以人工去分析js 但是要实现比较通用的功能,最好还是有通用的js解释器比较好。
    laputa736年前 (2012-11-22)回复
    • 说实话,对这部分的逻辑,我理解的也不透彻。 个人所能想到的,貌似是不是找找python监控80端口的http相关的请求,然后过滤,找出,你当然的模拟软件中所发出的请求,然后计算起始时间和结束时间,或许可以实现你的目的。 关于python中监控http的80端口这类的库,我也没折腾过,还是你自己找找吧。 可以参考: 去哪找python的第三方类库Python Package Index中有没有相关的你要的。
      crifan6年前 (2012-11-22)回复
      • 嗯。你说的这个思路,我也考虑过。不过之前对socket监听这块了解甚少。下面接着尝试一下吧,谢谢。
        laputa736年前 (2012-11-23)回复
  10. 你好,非常谢谢你的详细教程,仍在学习中!我使用了GB2312,可是还是乱码。 像这样,卤锚脟漏路脰脌脿 请问下我怎样才知道应该用什么方式解码才正确呢?
    JohnSmith6年前 (2012-11-21)回复
    • 请回答: 1.有没有下载我的代码,自己测试一下实际效果? 还是你自己另外写的代码? 2.如果是自己另外写的代码,请贴出相关代码。 然后才好帮你分析错误原因。
      crifan6年前 (2012-11-22)回复
      • 自己写的,但基本是照着教程来的。 import urllib2 import re from BeautifulSoup import BeautifulSoup def main(): userUrl = "http://www.xiami.com/u/5626235"; req = urllib2.Request(userUrl); resp = urllib2.urlopen(req); htmlSrc = resp.read(); htmlEncoding = "GB2312"; soup = BeautifulSoup(htmlSrc, fromEncoding=htmlEncoding); foundClass = soup.find(attrs={"href":"/u/5626235"}); foundString = foundClass.string; print foundString; if __name__ == "__main__": main();
        JohnSmith6年前 (2012-11-23)回复
14 queries in 0.236 seconds, using 10.58MB memory