可爱的 Python: 使用 mechanize 和 Beautiful Soup 轻松收集 Web 数据

可爱的 Python: 使用 mechanize 和 Beautiful Soup 轻松收集 Web 数据

使用 Python 工具简化 Web 站点数据的提取和组织

David Mertz, Ph.D., 开发人员, Gnosis Software, Inc.
David Mertz
从 2000 年开始,David Mertz 就一直在为 developerWorks 专栏 Charming PythonXML Matters 撰稿。您可以阅读他撰写的书籍 Text Processing in Python。有关 David 的更多信息,请访问其 个人主页

简介: 需要从 Web 页面收集数据时,可以使用 mechanize 库自动从 Web 站点收集数据并与之交互。通过 Mechanize 您可以填充表单并设置和保存 cookies,此外,Mechanize 提供了各种各样的工具来使 Python 脚本具备真正的 Web 浏览器的功能,可以与交互式 Web 站点进行交互。一款名为 Beautiful Soup 的常用配套工具帮助 Python 程序理解 Web 站点中包含的脏乱“基本是 HTML” 内容。

查看本系列更多内容

本文的标签:  python, web

 

 

标记本文!
 

 

发布日期: 2010 年 1 月 18 日
级别: 中级 其他语言版本: 英文
访问情况 4309 次浏览
建议: 0 (添加评论)

1 star2 stars3 stars4 stars5 stars 平均分 (共 2 个评分 )

 

与 David 联系

David 是我们最受欢迎的和多产的作者之一。查看 David 的个人资料,并与他以及 My developerWorks 上的其他作者和读者联系。

使用基本的 Python 模块,可以 编写脚本来与 Web 站点交互,但是如果没有必要的话,那么您就不希望这样做。Python 2.x 中的模块 urlliburllib2,以及 Python 3.0 中的统一的 urllib.* 子包,可以在 URL 的末尾获取资源。然而,当您希望与 Web 页面中找到的内容进行某种比较复杂的交互时,您需要使用 mechanize 库(参见 参考资料 获得下载链接)。

在自动化 Web scrap 或用户与 Web 站点的交互模拟中,最大的困难之一就是服务器使用 cookies 跟踪会话进度。显然,cookies 是 HTTP 头部的一部分,在 urllib 打开资源时会自然显示出来。而且,标准模块 Cookie(Python 3 中的 http.cookie)和 cookielib(Python 3 中的 http.cookiejar)有助于在比原始的文本处理更高的层次上处理这些头部。即使如此,在这个层次上执行处理也非常的繁琐。mechanize 库将这种处理提升到一个更高程度的抽象并使您的脚本 — 或交互性 Python shell — 表现出非常类似实际 Web 浏览器的行为。

Python 的 mechanize 受到 Perl 的 WWW:Mechanize 的启发,后者具有类似的一组功能。当然,作为长期的 Python 支持者,我认为 mechanize 更健壮,它看上去似乎继承了两种语言的通用模式。

mechanize 的一个亲密伙伴是同样出色的 Beautiful Soup 库(参见 参考资料 获得下载链接)。这是一个非常神奇的 “粗糙的解析器”,用于解析实际 Web 页面中包含的有效 HTML。您不需要 将 Beautiful Soup 用于 mechanize,反之亦然,但是多半情况下,当您与 “实际存在的 Web” 交互时,您将希望同时使用这两种工具。

一个实际示例

我曾在多个编程项目中使用过 mechanize。最近一个项目是从一个流行的 Web 站点中收集匹配某种条件的名称的列表。该站点提供了一些搜索工具,但是没有提供任何正式的 API 来执行此类搜索。虽然访问者可能能够更明确地猜出我过去在做什么,但我将修改给出的代码的细节,以避免暴露有关被 scrap 的站点或我的客户机的过多信息。一般情况下,我给出的代码对于类似任务是通用的。


入门工具

在实际开发 Web scrap/分析代码的过程中,我发现以交互式方式查看、处理和分析 Web 页面的内容以了解相关 Web 页面实际发生的操作是非常重要的功能。通常,站点中的一些页面是由查询动态生成(但是具有一致的模式),或是根据非常严格的模板预先生成。

完成这种交互式体验的一种重要方法就是在 Python shell 内使用 mechanize 本身,特别是在一个增强的 shell 内,比如 IPython(参见 参考资料 获得一个链接)。通过这种方式,您可以在编写执行希望用于生产中的交互的最终脚本之前,请求各种已链接的资源、提交表单、维护或操作站点 cookies,等等。

然而,我发现我与 Web 站点的许多实验性质的交互在实际的现代 Web 浏览器中得到了更好的执行。方便地呈现页面可以使您更加快速地了解给定页面或表单中正在发生的事情。问题在于,呈现页面仅仅完成了事情的一半,可能还不到一半。获得 “页面源代码” 会让您更进一步。要真正理解给定 Web 页面或与 Web 服务器的一系列交互的背后的原理,需要了解更多。

要了解这些内容,我常常使用 Firebug(参见 参考资料 获得链接)或面向 Firefox 的 Web Developer 插件(或最新 Safari 版本中的内置的可选 Develop 菜单,但是所针对的目标人群不同)。所有这些工具都可以执行诸如显示表单字段、显示密码、检查页面的 DOM、查看或运行 Javascript、观察 Ajax 通信等操作。比较这些工具的优劣需要另外撰写一篇文章,但是如果您要进行面向 Web 的编程的话,那么必须熟悉这些工具。

不管使用哪一种工具来对准备实现自动化交互的 Web 站点做实验,您都需要花比编写简洁的 mechanize 代码(用于执行您的任务)更多的时间来了解站点实际发生的行为。


搜索结果 scraper

考虑到上面提到的项目的意图,我将把包含 100 行代码的脚本分为两个功能:

  • 检索所有感兴趣的结果
  • 从被检索的页面中拉取我感兴趣的信息

使用这种方式组织脚本是为了便于开发;当我开始任务时,我需要知道如何完成这两个功能。我觉得我需要的信息位于一个普通的页面集合中,但是我还没有检查这些页面的具体布局。

首先我将检索一组页面并将它们保存到磁盘,然后执行第二个任务,从这些已保存的文件中拉取所需的信息。当然,如果任务涉及使用检索到的信息构成同一会话内的新交互,那么您将需要使用顺序稍微不同的开发步骤。

因此,首先让我们查看我的 fetch() 函数:


清单 1. 获取页面内容
				
import sys, time, os
from mechanize import BrowserLOGIN_URL = 'http://www.example.com/login'
USERNAME = 'DavidMertz'
PASSWORD = 'TheSpanishInquisition'
SEARCH_URL = 'http://www.example.com/search?'
FIXED_QUERY = 'food=spam&' 'utensil=spork&' 'date=the_future&'
VARIABLE_QUERY = ['actor=%s' % actor for actor in('Graham Chapman','John Cleese','Terry Gilliam','Eric Idle','Terry Jones','Michael Palin')]def fetch():result_no = 0                 # Number the output filesbr = Browser()                # Create a browserbr.open(LOGIN_URL)            # Open the login pagebr.select_form(name="login")  # Find the login formbr['username'] = USERNAME     # Set the form valuesbr['password'] = PASSWORDresp = br.submit()            # Submit the form# Automatic redirect sometimes fails, follow manually when neededif 'Redirecting' in br.title():resp = br.follow_link(text_regex='click here')# Loop through the searches, keeping fixed query parametersfor actor in in VARIABLE_QUERY:# I like to watch what's happening in the consoleprint >> sys.stderr, '***', actor# Lets do the actual query nowbr.open(SEARCH_URL + FIXED_QUERY + actor)# The query actually gives us links to the content pages we like,# but there are some other links on the page that we ignorenice_links = [l for l in br.links()if 'good_path' in l.urland 'credential' in l.url]if not nice_links:        # Maybe the relevant results are emptybreakfor link in nice_links:try:response = br.follow_link(link)# More console reporting on title of followed link pageprint >> sys.stderr, br.title()# Increment output filenames, open and write the fileresult_no += 1out = open(result_%04d' % result_no, 'w')print >> out, response.read()out.close()# Nothing ever goes perfectly, ignore if we do not get pageexcept mechanize._response.httperror_seek_wrapper:print >> sys.stderr, "Response error (probably 404)"# Let's not hammer the site too much between fetchestime.sleep(1)

对感兴趣的站点进行交互式研究后,我发现我希望执行的查询含有一些固定的元素和一些变化的元素。我仅仅是将这些元素连接成一个大的 GET 请求并查看 “results” 页面。而结果列表包含了我实际需要的资源的链接。因此,我访问这些链接(当此过程出现某些错误时,会抛出 try/except 块)并保存在这些内容页面上找到的任何内容。

很简单,是不是?Mechanize 可以做的不止这些,但是这个简单的例子向您展示了 Mechanize 的大致功能。


处理结果

现在,我们已经完成了对 mechanize 的操作;剩下的工作是理解在 fetch() 循环期间保存的大量 HTML 文件。批量处理特性让我能够在一个不同的程序中将这些文件整齐、明显地分离开来,fetch()process() 可能交互得更密切。Beautiful Soup 使得后期处理比初次获取更加简单。

对于这个批处理任务,我们希望从获取的各种 Web 页面的零散内容中生成表式的以逗号分隔的值(CSV)数据。


清单 2. 使用 Beautiful Soup 从无序的内容中生成整齐的数据
				
from glob import glob
from BeautifulSoup import BeautifulSoupdef process():print "!MOVIE,DIRECTOR,KEY_GRIP,THE_MOOSE"for fname in glob('result_*'):# Put that sloppy HTML into the soupsoup = BeautifulSoup(open(fname))# Try to find the fields we want, but default to unknown valuestry:movie = soup.findAll('span', {'class':'movie_title'})[1].contents[0]except IndexError:fname = "UNKNOWN"try:director = soup.findAll('div', {'class':'director'})[1].contents[0]except IndexError:lname = "UNKNOWN"try:# Maybe multiple grips listed, key one should be in theregrips = soup.findAll('p', {'id':'grip'})[0]grips = " ".join(grips.split())   # Normalize extra spacesexcept IndexError:title = "UNKNOWN"try:# Hide some stuff in the HTML <meta> tagsmoose = soup.findAll('meta', {'name':'shibboleth'})[0]['content']except IndexError:moose = "UNKNOWN"print '"%s","%s","%s","%s"' % (movie, director, grips, moose)

第一次查看 Beautiful Soup,process() 中的代码令人印象深刻。读者应当阅读有关文档来获得关于这个模块的更多细节,但是这个代码片段很好地体现了它的整体风格。大多数 soup 代码包含一些对只含有格式良好的 HTML 的页面的 .findAll() 调用。这里是一些类似 DOM 的 .parentnextSiblingpreviousSibling 属性。它们类似于 Web 浏览器的 “quirks” 模式。我们在 soup 中找到的内容并不完全 是一个解析树。


结束语

诸如我之类的守旧者,甚至于一些更年轻的读者,都会记住使用 TCL Expect(或使用用 Python 和其他许多语言编写的类似内容)编写脚本带来的愉悦。自动化与 shell 的交互,包括 telnet、ftp、ssh 等等远程 shell,变得非常的直观,因为会话中的所有内容都被显示出来。Web 交互变得更加细致,因为信息被分为头部和内容体,并且各种相关的资源常常通过 href 链接、框架、Ajax 等被绑定在一起。然而,总的来说,您可以 使用 wget 之类的工具来检索 Web 服务器提供的所有字节,然后像使用其他连接协议一样运行与 Expect 风格完全相同的脚本。

在实践中,几乎没有编程人员过分执着于过去的老方法,比如我建议的 wget + Expect 方法。Mechanize 保留了许多与出色的 Expect 脚本相同的东西,令人感觉熟悉和亲切,并且和 Expect 一样易于编写(如果不是更简单的话)。Browser() 对象命令,比如 .select_form().submit().follow_link(),真的是实现 “查找并发送” 操作的最简单、最明显的方法,同时绑定了我们希望在 Web 自动化框架中具备的复杂状态和会话处理的所有优点。

转载于:https://www.cnblogs.com/babykick/archive/2011/05/27/2059828.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

广西工学院c语言试题答案,广西工学院的C语言考试试题

广西工学院鹿山学院 2005 — 2006 学年第 2 学期课程考核试题 考核课程 《C语言程序设计》 (A卷)考核班级 学生数 印数 考核方式 闭卷 考核时间 120 分钟一、选择题(每题2分&#xff0c;共40分)1. 一个C语言的源程序中&#xff0c; 。A&#xff0e;必须有一个主函数2. 下列数据…

JavaScript 断点调试技巧

大家好&#xff0c;我是若川。最近组织了源码共度活动&#xff1a;1个月&#xff0c;200人&#xff0c;一起读了4周源码&#xff0c;参与的小伙伴都表示收获很大。如果感兴趣可以点击链接扫码加我微信 ruochuan12。之前推荐过很多次调试文章&#xff0c;说明调试的重要性&#…

大学生电子设计大赛案例分析_为大学生设计问答平台—案例研究

大学生电子设计大赛案例分析Dealing with academic-related questions like picking a course, fulfilling a major requirement can be tedious and ineffective when you have to simultaneously balance school work, social activities, and focus on personal growth and …

最新最详细最简洁Eclipse调试PHP配置详解(Xdebug,Zend Debugger)

搬家注&#xff1a;该日志写于2011 年 04 月 07 日&#xff0c;Eclipse&#xff0c;PHP等版本号很多&#xff0c;更新也比较快&#xff0c;请注意文章中的版本。本文不一定帮您解决问题&#xff0c;但能给您一些解决问题的思路及一些概念。 最近开始做SRTP项目WebOS&#xff0c…

按键精灵易语言c,求助(把按键精灵的源码转为易语言的)

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼MoveTo 1203,673IfColor 1203,673,"252489",2 ThenMoveTo 417, 242Delay 10072LeftDown 1LeftClick 1LeftUp 1MoveTo 982, 551Delay 7660LeftDoubleClick 1Delay 10Delay 30LeftUp 1LeftUp 1LeftUp 1MoveTo 1102, 709Del…

入门前端学习路线图【送书】

大家好&#xff0c;我是若川。记得点上方音频听小姐姐配音&#xff0c;超级好听。华章图书又赞助了书籍送福利给大家。本次送4本书的抽奖方式是&#xff1a;截止到9月6日&#xff08;周一&#xff09;20:00&#xff0c;在留言区留言任意内容。我会在留言区抽取「1位」关注我公众…

单选按钮设置为被选中状态_为什么要设置错误的按钮状态

单选按钮设置为被选中状态当正确的方法出错时 (When the right way goes wrong) Let’s say you want to create a click effect on an HTML button. The first idea that many people get is to do something that reproduces the feeling of the sound emitted by a real but…

「娃娃分享」-常见自校检分析实例.

自校检是许多软件的保护手段之一&#xff0c;对软件加个简单的壳再增加自校检在一定程序上可以抵挡住一大部分新手&#xff0c;不过&#xff0c;对许多人来说&#xff0c;这个保护已经很弱了。。下面讲几种常见的解决自校检方法&#xff0c;写的粗略&#xff0c;希望大家补充。…

用VC和MinGW导出dll的def和lib(a)文件

为什么80%的码农都做不了架构师&#xff1f;>>> 原文地址&#xff1a;http://zhangyafeikimi.iteye.com/blog/404580 有了dll文件需要导出def文件&#xff1a; pexports zlib1.dll > zlib1.def 有了dll和def文件&#xff0c;需要导出MinGW的.a文件&#xff1a;…

51中断编程c语言,[新人求指教]51C语言编程可否用中断令循环结束提早结束

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼C51_C语言编程控制流水灯硬件电路 p0 接 led 8 个&#xff0c;P33 接按键使用中断2开机灯按1~8逐位闪烁&#xff0c;并循环按键后改为 两灯亮 的流水灯下面写了个程序#include #include #define uchar unsigned char#define uint u…

产品设计美学案例分析_美学在产品设计中的重要性

产品设计美学案例分析重点 (Top highlight)In one of my previous jobs, I had really interesting debates with the CEO regarding whether we should spend more time improving the way our app looks and feels. ‘How could he not care that the design is outdated?! …

即将到来的ECMAScript 2022标准

大家好&#xff0c;我是若川。周末分享一篇相对简单的文章。最近组织了源码共度活动&#xff1a;1个月&#xff0c;200人&#xff0c;一起读了4周源码&#xff0c;参与的小伙伴都表示收获很大。如果感兴趣可以点击链接扫码加我微信 ruochuan12。另外&#xff1a;昨天的推文入门…

c语言中二叉树中总结点,C语言二叉树的三种遍历方式的实现及原理

二叉树遍历分为三种&#xff1a;前序、中序、后序&#xff0c;其中序遍历最为重要。为啥叫这个名字&#xff1f;是根据根节点的顺序命名的。比如上图正常的一个满节点&#xff0c;A&#xff1a;根节点、B&#xff1a;左节点、C&#xff1a;右节点&#xff0c;前序顺序是ABC(根节…

动态库的创建与使用

1、动态库文件的创建 &#xff08;1&#xff09;编写源文件 &#xff08;2&#xff09;编译生成动态库 g -fPIC -shared -o libfile_operation.so file_operation.cpp 此编译过程分为两步&#xff0c;等同于下面的两个命令&#xff1a; g -c -fPIC file_operation.cpp …

ux设计中的各种地图_UX写作中的移情

ux设计中的各种地图Demetri Martin is a master of comedic situations. If you’ve never seen Demetri Martin是喜剧情境的大师。 如果你从未见过 him before, he has a sort of dry brand of observational humor, relying more on anecdotes than full stories, and often…

字符串搜索。HOJ1530 Compound Words。

stl set实现字符串搜索。。效率一般。(附二分搜索。) Compound WordsTime limit:1sec.Submitted:233Memory limit:32MAccepted:81Source: Waterloo ACM Programming Contest Sep 28, 1996 You are to find all the two-word compound words in a dictionary. A two-word compo…

字节3-1前端面试官自学Vue的正确姿势

大家好&#xff0c;我是若川。前不久和一个字节前端TL朋友聊天&#xff0c;说到大厂前端供需脱节的情况。特别是使用Vue框架的&#xff0c;因为简单易学好上手&#xff0c;但是能够深入理解的人并不多&#xff0c;大多都只停留在应用层面&#xff0c;缺乏更深层面的理解。尤其是…

android视图工具,android studio的HierarchyViewer工具如何知道android屏幕的视图属性

让我们首先看看adb是如何组织的.它有3个主要组件,如here所述 –> client – 在用于开发的机器上运行的客户端.通过发出adb命令从shell调用客户端.层次结构查看器还会创建adb客户端.> server – 在开发计算机上作为后台进程运行的服务器.它将从adb客户端发出的命令传递给a…

云时代架构读后感4--IT架构的本质

IT架构的本质 原文地址&#xff1a;http://mp.weixin.qq.com/s?__bizMzAwNTQ4MTQ4NQ&mid2453562304&idx1&snbe86a7bc682c4e76e06b87a10ad45188&chksm8cd136a2bba6bfb430103e50f94b670e799412d0a1cae4eded0eb901847b6d462359ae317635&mpshare1&scene23…

苹果风格ui_苹果如何使Soft-UI成为未来

苹果风格ui重点 (Top highlight)Apple announced some pretty wild updates at WWDC 2020 today.苹果今天在WWDC 2020上宣布了一些相当疯狂的更新。 But technology aside, let’s focus on how their UI has changed. It went through the first bitmap representations, thr…