屏幕抓取
下面是一个urllib+re屏幕抓取的例子:
from urllib import urlopen
import re
text = urlopen('http://python.org/community/jobs').read()
pat = re.compile('<a class=".*?" href=".*?">.*?</a>')
for url in pat.findall(text):
print '%s' % url
下面将会介绍解决上面以re模块为基础的屏幕抓取例子中问题的两个解决方案:1、使用程序调用Tidy库,进行XHTML解析;2、使用Beautiful Soup库,它专门为屏幕抓取设计。
还有其他屏幕抓取供Python使用,比如scrape.py
Tidy和XHTML解析
XHTML是HTML的最新方言,是XML的一种形式。
Python标准库中有很多支持结构化格式解析的库,例如HTML和XML(http://python.org/doc/lib/markup.html)
sgmllib和htmllib是基于事件的,可以解析非常乱的HTML
Tidy
Tidy是用来修复非常乱且不规范的HTML文档的工具
获取Tidy
-
安装tidy
Ubuntu:apt-get install tidy
window:推荐一种感觉不是特别好的方法,通过cygwin安装:
cygwin搜索tidy
如上如,找到tidy后勾选后面的复选框点击下一步安装即可
-
安装tidylib
Ubuntu:pip install pytidylib
windows:pip install pytidylib
假设桌面有一个zhubao.html,下面是一个利用tidy修复不规范的HTML代码的例子
from subprocess import Popen,PIPE
from urllib import urlopen
text=open('C:\users\hcs\desktop\zhubao.html').read()
tidy=Popen('tidy',stdin=PIPE,stdout=PIPE,stderr=PIPE,shell=True)
#print tidy
tidy.stdin.write(text)
tidy.stdin.close()
print tidy.stdout.read()
为什么用XHTML
XHTML对显式关闭所有的元素要求更加严格,所以它更容易解析
它是XML的一种,所以可以对它使用XML的工具,如xpath
解析从tidy获得的表现良好的XHTML的方法是使用标准库模块(和类)HTMLParser(这里注意它和htmllib模块中HTMLParser的区别)
使用HTMLParser
HTMLParser的回调方法
方法 | 调用时间 |
---|---|
handle_starting(tag, attrs) | 找到开始标签时调用。attrs是(名称、值)对的序列 |
handle_startendtag(tag, attrs) | 使用空标签时调用。默认分开处理开始和结束标签 |
handle_endtag(tag) | 找到结束标签时调用 |
handle_data(data) | 使用文本数据时调用 |
handle_charref | 当使用&#ref;形式的实体引用时调用 |
handle_entityref(name) | 当使用&name形式的实体引用时调用 |
handle_comment(data) | 注释时调用。只对注释内容调用 |
handle_decl(decl) | 声明<!...>形式时调用 |
handle_pi(data) | 处理指令时调用 |
from urllib import urlopen
from HTMLParser import HTMLParser
class handler(HTMLParser):
in_h3 = False
in_link = False
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag == 'h3':
self.in_h2 = True
if tag == 'a' and 'href' in attrs:
self.in_link = True
self.chunks = []
self.url = attrs['href']
def handle_data(self, data):
if self.in_link:
self.chunks.append(data)
def handle_endtag(self, tag):
if tag == 'h3':
self.in_h3 = False
if tag == 'a':
if self.in_h3 and self.in_link:
print '%s (%s)' % (''.join(self.chunks), self.url)
self.in_link = False
text = urlopen(' ').read()
parser = handler()
parser.feed(text)
parser.close()
Beautiful Soup
Beautiful Soup是一个小模块,可以解析很乱的HTML文档。
安装:pip install beautifulsoup4
例子:
from urllib import urlopen
from bs4 import BeautifulSoup
text = urlopen('http://python.org/community/jobs').read()
soup = BeautifulSoup(text)
jobs = set()
for header in soup('h3'):
links = header('a', 'reference')
if not links: continue
link = links[0]
jobs.add('%s (%s)' % (link.string, link['href']))
print '\n'.join(sorted(jobs, key = lambda s : s.lower()))
使用CGI创建动态网页
CGI]:通用网关接口,是一种基本的万维网程序设计技术,是网络服务器可以将查询传递到专门的程序中并且在网页张显示结果的标准机制,Python内进行CGI程序设计请参考http://wiki.python.org/moin/WebProgramming
python库参考的CGI部分,可以查看Python的cgi模块的详细信息,cgitb也是Python CGI脚本开发的一个重要的模块。
CGI脚本编好后,将它放入服务器可访问地方,再加入pound bang行,再设置好文件权限就可以访问了
使用cgitb调试
Python2.2的标准库中增加了叫cgitb(用于CGI回溯)的模块,导入它并且调用它的enable函数,就能得到包含错误信息的网页,如下CGI脚本
#!/usr/lib/env python
import cgitb; cgitb.enable()
print 'Content-type: text/html'
print
print 1/0
print 'Hello World'
使用cgi模块
Python可以通过cgi模块的FieldStorage类从CGI脚本中获取用户输入(通过HTML表单提供给CGI脚本的键-值对)
form = cgi.FieldStorage()
name1 = form['name'].value
name2 = form.getvalue('name', 'Unknow')
#name2和name1等效
不用表单调用CGI脚本
可以在脚本的URL后面加上问号,然后添加用&分隔的键值对来达到这个效果。例如下面的URL:
http://www.someserver.com/name.cgi?name=zhangsan&age=13
可以通过如下代码创建此类查询
>>> import urllib
>>> urllib.urlencode({'name':'zhangsan', 'age':'42'})
'age=42&name=zhangsan'
简单的表单
关于HTML的一些资源
- http://www.webreference.com/htmlform
- http://www.htmlhelp.com/faq/html/forms.html
- http://www.cs.tut.fi/~jkorpela/forms
- http://www.w3schools.com/html/html1_forms.asp
- http://www.htmlgoodies.com/tutors/fm.html
从CGI脚本获取信息的方法有两种:GET和POST方法
网友评论