用Python创建垃圾邮件列表的网页爬虫
大家好,我不是想做什么坏事,我只是需要做一些作业。我是个新手程序员,正在使用Python 3.0,但在用递归解决问题时遇到了困难。我在这个问题上卡了很久。以下是作业内容:
作业:
写一个递归方法spam(url, n),这个方法接收一个网页的URL和一个非负整数n,收集网页中所有的电子邮件地址,并把它们添加到一个全局字典变量spam_dict中,然后对网页中包含的每个http链接递归调用自己。
你会使用字典,这样每个电子邮件地址只会保存一份;你的字典会存储(键,值)对(电子邮件,电子邮件)。递归调用时应该用参数n-1,而不是n。如果n=0,你应该收集电子邮件地址,但不应该进行递归调用。参数n用于限制递归的深度,最多为n。
你需要使用上面两个问题的解决方案;你的方法spam()会调用方法links2()和emails(),可能还会调用其他函数。
注意事项:
- 直接运行spam()不会在屏幕上产生任何输出;要查看你的spam_dict,你需要读取spam_dict的值,并且在每次运行spam之前需要将其重置为空字典。
- 记得如何使用全局变量。
使用方法:
>>> spam_dict = {}
>>> spam('http://reed.cs.depaul.edu/lperkovic/csc242/test1.html',0)
>>> spam_dict.keys()
dict_keys([])
>>> spam_dict = {}
>>> spam('http://reed.cs.depaul.edu/lperkovic/csc242/test1.html',1)
>>> spam_dict.keys()
dict_keys(['lperkovic@cs.depaul.edu', 'nobody@xyz.com'])
到目前为止,我写了一个函数,可以遍历网页并把所有链接放在一个漂亮的小列表里,我想做的是调用那个函数。那我为什么要在字典上使用递归呢?怎么用?我不明白n在这一切中有什么作用。
def links2(url):
content = str(urlopen(url).read())
myparser = MyHTMLParser()
myparser.feed(content)
lst = myparser.get()
mergelst = []
for link in lst:
mergelst.append(urljoin(lst[0],link))
print(mergelst)
任何输入(除了为什么spam不好)都将非常感激。此外,我意识到上面的函数可能看起来更好,如果你有办法做到这一点,我很乐意听。不过,我只需要程序能产生正确的输出。
补充:
我写了一个函数,可以从页面中收集电子邮件,但我不确定如何把.com、.edu和.org都放在一起。
from re import findall
def emails(url):
links = str(links3(url))
# how do I construct pattern?
pattern='[A-Za-z0-9_.]+\@[A-Za-z0-9_.]+.com\.edu\.org
lst = findall(pattern,links)
print(lst)
我该怎么告诉Python呢?我在文档中找不到相关内容。
2 个回答
n
在这里是个关键,它的作用是限制递归调用的最大“深度”。
简单来说,因为你是在一个已经运行的扫描中不断调用扫描邮箱的功能,所以会形成一个调用堆栈,记录着每次调用的情况。随着你不断地递归调用扫描器,这个堆栈会越来越深。
你不希望这个过程无限进行下去,所以你需要传递一个整数作为参数,每次调用时把这个整数减一。当这个整数减到0的时候,你就停止递归调用,让之前的调用逐渐结束。
call 1 (args...., n=3)
call 2a (args...., n=2)
call 3 (args...., n=1)
call 4a (args..., n=0) <-- these calls won't call more scans
call 4b (args..., n=0) <-- because n=0, so this is max depth
call 2b (args...., n=2)
想想递归是怎么回事。你希望你的函数在某些情况下能够自己调用自己。为了做到这一点,你需要给你的函数添加一个参数,用来表示递归的层级,然后你需要弄清楚在不同的情况下它应该做些什么。
最基本的情况是,当n=0时,它应该做什么?(提示:你差不多已经明白了)
如果n=1,它应该怎么做?你可能想要在你现有列表的每个元素上再次调用你的函数,这次用n=0。
如果n大于1呢?你想要在你目前拥有的每个元素上再次调用你的函数,这次用n = n-1。