根据网页源码提取url
自学3天后,写出了这个,代码很笨拙,自己也觉得,我觉得遇到的最大的困难就是缩进和方法名不熟。
看来还是要多加练习啊
原题是这样的:
测试时间为一周,接受测试人员领取试题,通过看书和搜索学习之后作答,并以电子邮件形式回复。期间有任何关于Python的问题也可以发送电子邮件询问,作者会在不影响测试效果的情况下尽快回答。
参考书目可以只看《简明Python教程》,沈洁元译。使用的Python版本为2.5.4,不要使用其他版本。
测试题目
----------
分析科学松鼠会的网站首页。
使用自己方便的方法下载科学松鼠会网站的首页,并保存为一个文件。然后通过程序分析该问题提取其中的所有URL,并将这些URL以每行一个的方式输出到一个文本文件中。
测试内容主要面向字符串分析和简单文件操作。
细节提示
----------
#. 输出的URL列表必须是完整的URL,包括松鼠会的域名。例如 ``http://songshuhui.net/wp-content/themes/isongshu/style.css`` 。
#. 可以利用任何浏览器打开松鼠会首页,然后在页面单击邮件,查看源代码并保存。
#. 注意相对URL的分析,"/"开头的是根URL,前面加域名等前缀即可,否则则是相对URL,需要提取相关的当前路径。
#. 注意打开源文件时的编码字符集。
#. 去掉重复的URL。
#. 可以忽略掉JavaScript代码中的拼接URL。
#. 最多产生URL的标签是"<a>"和"<img>",其他的标签也需要分析,并影响评分。
#. URL不会被切分多多行,一般来说URL是在双引号中。
主要困难出在不知道如何判断相对url,采用方法是根据标签提取属性的内容。
--------------------------------------------
#!C:\Python25\python.exe
#-*- encoding: gb2312 -*-
#使用版本为2.5.4
#下载首页命名为songshuhui[1].txt
#在做这个题的时候,想到了两个办法,一个是以“为分隔符分割整片源代码,后来觉得这样不准确,于是又改为是根据标签来解析标签下href的值,然后筛选后再用别的方法解析用标签没有解析到的。
import HTMLParser
import re
class MyParser(HTMLParser.HTMLParser):
def __init__(self):
HTMLParser.HTMLParser.__init__(self)
self.listOld = []
#这里是用handle_comment来解析源码中<!--注释中的url
def handle_comment(self, data):
if data.find(" http://")>0:
url = re.search("( http://.*)", data).group(1)
self.listOld.append(url)
#这里主要就是对标签下的属性进行url提取
def handle_starttag(self, tag, attrs):
# 这里重新定义了处理开始标签的函数
if tag == 'a':
# 判断标签<a>的属性
for name,value in attrs:
#如果<a>标签下的<href>的值内不包含<,这么做的原因是因为测试中发现有一个标签<a>的herf是一个<img>,相当于<a>里面嵌套了标签<img>,所以多加一层判断
if value.find("<")<0:
#属性名为href并且该值不为空
if name == 'href' and value!= '':
#如果这个值里包括http就说明是绝对路径
if value.find('http')>-1:
#绝对路径就直接保存至listOld里面
self.listOld.append(value)
else:
#相对路径的话就在前面加上http://songshuhui.net
self.listOld.append('http://songshuhui.net/' + value)
#提取harf中img标签的src的值
else:
#从href里面提取出img的src。根据=分割后的第一个值,去掉最后一个字符">"
self.listOld.append(value.split("=")[1][0:len(value.split("=")[1])-1])
elif tag == 'link':
# 判断标签<link>的属性
for name,value in attrs:
if name =='href' and value!= '':
#如果是绝对路径
if value.find('http')>-1:
self.listOld.append(value)
else:
#如果是相对路径
self.listOld.append('http://songshuhui.net/'+value)
elif tag == 'img':
# 判断标签<img>的属性
for name,value in attrs:
if name == 'src' and value!= '':
#如果是绝对路径
if value.find('http')>-1:
self.listOld.append(value)
#如果是相对路径
else:
self.listOld.append('http://songshuhui.net/'+value)
elif tag == 'form':
# 判断标签<form>的属性
for name,value in attrs:
#提取form的action属性值
if name == 'action' and value!='':
self.listOld.append(value)
elif tag == 'div':
# 判断标签<form>的属性
for name,value in attrs:
#提取div的onclick属性值,以'为分隔,的第一个值,并且包含http
if name == 'onclick' and value != '' and value.find('http')>-1:
#print "测试onclick的值:"+value.split('\'')[1]
#结果加入到listOld中
self.listOld.append(value.split('\'')[1])
if __name__ == '__main__':
#获取源代码
fileA=open('songshuhui[1].txt')
a=fileA.read()
my = MyParser()
# 传入要分析的数据,也就是科学松鼠会首页
my.feed(a)
d={}
#这里是去重
for urls in my.listOld:
if not d.has_key(urls):
d[urls]=""
nlst=[]
for key in d.keys():
nlst.append(key)
#创建SSH.txt,把最终去重后的结果逐行写入
fileB=open('SSHurl.txt','w')
for urlstr in nlst:
fileB.write(urlstr + '\n')
print 'OK!'
#清理工作
fileB.close()
fileA.close()
#!C:\Python25\python.exe#-*- encoding: gb2312 -*-#使用版本为2.5.4#下载首页命名为songshuhui[1].txt#在做这个题的时候,想到了两个办法,一个是以“为分隔符分割整片源代码,后来觉得这样不准确,于是又改为是根据标签来解析标签下href的值,然后筛选后再用别的方法解析用标签没有解析到的。import HTMLParserimport reclass MyParser(HTMLParser.HTMLParser): def __init__(self): HTMLParser.HTMLParser.__init__(self) self.listOld = [] #这里是用handle_comment来解析源码中<!--注释中的url def handle_comment(self, data): if data.find(" http://")>0: url = re.search("( http://.*)", data).group(1) self.listOld.append(url) #这里主要就是对标签下的属性进行url提取 def handle_starttag(self, tag, attrs): # 这里重新定义了处理开始标签的函数 if tag == 'a': # 判断标签<a>的属性 for name,value in attrs: #如果<a>标签下的<href>的值内不包含<,这么做的原因是因为测试中发现有一个标签<a>的herf是一个<img>,相当于<a>里面嵌套了标签<img>,所以多加一层判断 if value.find("<")<0: #属性名为href并且该值不为空 if name == 'href' and value!= '': #如果这个值里包括http就说明是绝对路径 if value.find('http')>-1: #绝对路径就直接保存至listOld里面 self.listOld.append(value) else: #相对路径的话就在前面加上http://songshuhui.net self.listOld.append('http://songshuhui.net/' + value) #提取harf中img标签的src的值 else: #从href里面提取出img的src。根据=分割后的第一个值,去掉最后一个字符">" self.listOld.append(value.split("=")[1][0:len(value.split("=")[1])-1]) elif tag == 'link': # 判断标签<link>的属性 for name,value in attrs: if name =='href' and value!= '': #如果是绝对路径 if value.find('http')>-1: self.listOld.append(value) else: #如果是相对路径 self.listOld.append('http://songshuhui.net/'+value) elif tag == 'img': # 判断标签<img>的属性 for name,value in attrs: if name == 'src' and value!= '': #如果是绝对路径 if value.find('http')>-1: self.listOld.append(value) #如果是相对路径 else: self.listOld.append('http://songshuhui.net/'+value) elif tag == 'form': # 判断标签<form>的属性 for name,value in attrs: #提取form的action属性值 if name == 'action' and value!='': self.listOld.append(value) elif tag == 'div': # 判断标签<form>的属性 for name,value in attrs: #提取div的onclick属性值,以'为分隔,的第一个值,并且包含http if name == 'onclick' and value != '' and value.find('http')>-1: #print "测试onclick的值:"+value.split('\'')[1] #结果加入到listOld中 self.listOld.append(value.split('\'')[1])if __name__ == '__main__': #获取源代码 fileA=open('songshuhui[1].txt') a=fileA.read() my = MyParser() # 传入要分析的数据,也就是科学松鼠会首页 my.feed(a) d={} #这里是去重 for urls in my.listOld: if not d.has_key(urls): d[urls]="" nlst=[] for key in d.keys(): nlst.append(key) #创建SSH.txt,把最终去重后的结果逐行写入 fileB=open('SSHurl.txt','w') for urlstr in nlst: fileB.write(urlstr + '\n') print 'OK!' #清理工作 fileB.close() fileA.close()