迭代相同类型对象中的对象列表

时间:2013-05-18 03:26:43

标签: python-2.7

我正在尝试制作网页的对象图(边缘是页面之间的'相关'链接)。一旦我开始工作,我将使用键作为URL创建一个对象字典,这样我就不会创建同一页面的多个对象。

我有一个类Page(),内部页面是一个填充了Page()类型对象的列表。我在我的根页面对象上调用了函数root.crawlRelated()。这会填充列表。然后我尝试遍历列表并调用obj.crawlRelated()。我的目标是在root.related []中填充每个对象Page()及其相关页面列表。

在我抓取的网站上,每个页面都有5个相关的链接,所以在两代之后应该有5个相关的对象,每个对象应该有5个相关的对象。我遇到的问题是crawlRelated()方法将所有对象附加到root而不是root.related中的相应对象。

from urllib import urlopen
#from bs4 import BeautifulSoup
import re

####################CLASS PAGE######################
class Page():

    __title = ""
    __link = ""
    related = []
    __relatedURLs = []

    def __init__(self, title, link, relatedURLs):
        self.__title = title
        self.__link = link
        self.__relatedURLs = relatedURLs

    def get_attributes(self,key):
        return self.__attributes.get(key,None)

    def get_relatedURLs(self):
        return self.__relatedURLs

    def get_title(self):
        return self.__title

    def crawl(self,url):
        webpage = urlopen(url).read()
        patFinderTitle = re.compile('<title>(.*)</title>')
        patFinderLink = re.compile('<link rel="canonical" href="([^"]*)" />')
        patFinderRelated = re.compile('<li><a href="([^"]*)"')

        findPatTitle = re.findall(patFinderTitle, webpage)
        findPatLink = re.findall(patFinderLink, webpage)
        findPatRelated = re.findall(patFinderRelated, webpage)

        self.related.append(Page(findPatTitle,findPatLink,findPatRelated))

    def crawlRelated(self):
        for link in self.__relatedURLs:
            self.crawl(link)
            print 'crawled related in', self.__title
####################END CLASS######################           


print 'doing some work...'
webpage = urlopen('http://medtwice.com/am-i-pregnant/').read()

patFinderTitle = re.compile('<title>(.*)</title>')
patFinderLink = re.compile('<link rel="canonical" href="([^"]*)" />')
patFinderRelated = re.compile('<li><a href="([^"]*)"')

findPatTitle = re.findall(patFinderTitle, webpage)
findPatLink = re.findall(patFinderLink, webpage)
findPatRelated = re.findall(patFinderRelated, webpage)

print 'found the webpage', findPatTitle

root = Page(findPatTitle,findPatLink,findPatRelated)
print 'Now crawling', root.get_relatedURLs()
root.crawlRelated()
print 'done crawling related'
print 'crawling related gen 2...'

i = 0
for rel in root.related:
    print 'crawling', rel#.get_title()
    #print rel.get_relatedURLs()
    rel.crawlRelated()
    i += 1
    if i > 3:
        break

print 'done crawling related gen 2'
print root.related
print len(root.related)
print len(root.related[0].related)

if i&gt; 3:break line是为了防止由于这个bug而发生的无限循环。

这行代码运行后

print len(root.related)
print len(root.related[0].related)
>> 25
>> 25

我希望它返回

>>5
>>5

我做错了什么?感谢。

1 个答案:

答案 0 :(得分:0)

密钥位于代码的这一部分:

class Page():

    __title = ""
    __link = ""
    related = []
    __relatedURLs = []

    def __init__(self, title, link, relatedURLs):
        self.__title = title
        self.__link = link
        self.__relatedURLs = relatedURLs

您已将related声明为类变量。这意味着类Page的所有实例共享一个数组。无论您是访问root.related还是rel.related等,它都是相同的数组。因此,当您访问rel.related时,您添加的任何内容(例如crawl(在root.related方法中)也会显示。

解决方案是使related成为实例变量,只需在构造函数中赋值即可。当你在它的时候,你应该删除类变量的其他声明,因为它们被相应的实例变量掩盖了。基本上,像这样开始你的课程:

class Page():
    def __init__(self, title, link, relatedURLs):
        self.__title = title
        self.__link = link
        self.__relatedURLs = relatedURLs
        self.related = []