【问题标题】:Class crawler written in python throws attribute errorpython写的类爬虫抛出属性错误
【发布时间】:2017-12-26 16:51:44
【问题描述】:

在用python写了一些代码之后,我陷入了深深的困境。我是在 python 中遵循 OOP 设计编写代码的新手。我在代码中使用的 xpath 完美无缺。通过“page_crawler”类的实例在“info_grabber”类中运行“passing_links”方法时,我迷失了方向。每次我运行我的代码时,我都会收到一个错误“'page_crawler' 对象没有属性 'passing_links'”。也许我写我的类爬虫的方式不是它应该的样子。但是,由于我已经花了几个小时在它上面,所以我想我可能会得到任何关于我应该纠正哪些行以使其工作的建议。提前感谢您查看它:

from lxml import html
import requests

class page_crawler(object):

    main_link = "https://www.yellowpages.com/search?search_terms=pizza&geo_location_terms=San%20Francisco%2C%20CA"
    base_link = "https://www.yellowpages.com"

    def __init__(self):

        self.links = [self.main_link]


    def crawler(self):
        for link in self.links:
            self.get_link(link)

    def get_link(self, link):

        print("Running page "+ link)
        page = requests.get(link)
        tree = html.fromstring(page.text)
        item_links = tree.xpath('//h2[@class="n"]/a[@class="business-name"][not(@itemprop="name")]/@href')
        for item_link in item_links:
            return self.base_link + item_link

        links = tree.xpath('//div[@class="pagination"]//li/a/@href')
        for url in links:
            if not self.base_link + url in self.links:
                self.links += [self.base_link + url]



class Info_grabber(page_crawler):

    def __init__(self, plinks):
        page_crawler.__init__(self)
        self.plinks = [plinks]

    def passing_links(self):
        for nlink in self.plinks:
            print(nlink)
            self.crawling_deep(nlink)

    def crawling_deep(self, uurl):

        page = requests.get(uurl)
        tree = html.fromstring(page.text)

        name = tree.findtext('.//div[@class="sales-info"]/h1')
        phone = tree.findtext('.//p[@class="phone"]')
        try:
            email = tree.xpath('//div[@class="business-card-footer"]/a[@class="email-business"]/@href')[0]
        except IndexError:
            email=""

        print(name, phone, email)


if __name__ == '__main__':

    crawl = Info_grabber(page_crawler)
    crawl.crawler()
    crawl.passing_links()

现在执行时,当它到达“self.crawling_deep(nlink)”行时,我收到一个新错误“raise MissingSchema(error)”

【问题讨论】:

  • 如果您还没有 - 看看scrapy - 它可以让您免于重新发明轮子。
  • 感谢 Jon Clements 先生的评论。我也和scrapy一起工作过。我想知道类的基本模式和不同的方面。再次感谢。
  • 我认为您的意思是使用字符串 ( url ) 启动 Info_grabber 实例,而您在 plinks 中传递了一个 page_crawler 对象,这会在您尝试时使您的程序崩溃在crawling_deep 方法中使用requests 来“获取”它。轻松修复:crawl = Info_grabber('http://some.url')。它不会使您的程序崩溃,但我怀疑它会给您带来预期的结果。我知道您正在尝试通过这个项目提高您的 OOP 技能,但我认为您过于复杂了。
  • 感谢 t.m.adam 先生的热心回答。我给 Info_grabber 类提供了一个 url,它确实为单个链接获取了预期的结果。但是,在我的 page_crawler 类中,我注意到它能够生成 400 个链接,我想将这些链接传递给 Info_grabber 类,但找不到任何想法。这是这 400 个新生成的链接中的一个链接,以查看结果。 crawl = Info_grabber('yellowpages.com/san-francisco-ca/mip/…) 需要注释掉 parse.crawler()。

标签: python python-3.x oop web-scraping


【解决方案1】:

我不确定我是否理解您在 page_crawler.get_link 中尝试执行的操作,但我认为您应该采用不同的方法来收集“分页”链接。
我将Info_grabber.plinks 重命名为Info_grabber.links,以便page_crawler.crawler 可以访问它们,并设法从多个页面中提取信息,但是代码远非理想。

class page_crawler(object):

    main_link = "https://www.yellowpages.com/search?search_terms=pizza&geo_location_terms=San%20Francisco%2C%20CA"
    base_link = "https://www.yellowpages.com"

    def __init__(self):
        self.links = []
        self.pages = []

    def crawler(self):
        for link in self.links:
            self.get_link(link)

    def get_link(self, link):
        print("Running page "+ link)
        page = requests.get(link)
        tree = html.fromstring(page.text)
        item_links = tree.xpath('//h2[@class="n"]/a[@class="business-name"][not(@itemprop="name")]/@href')
        for item_link in item_links:
            if not self.base_link + item_link in self.links:
                self.links += [self.base_link + item_link]

    def get_pages(self, link):
        page = requests.get(link)
        tree = html.fromstring(page.text)
        links = tree.xpath('//div[@class="pagination"]//li/a/@href')
        for url in links:
            if not self.base_link + url in self.pages:
                self.pages += [self.base_link + url]


class Info_grabber(page_crawler):

    def __init__(self, plinks):
        page_crawler.__init__(self)
        self.links += [plinks]

    def passing_links(self):
        for nlink in self.links:
            print(nlink)
            self.crawling_deep(nlink)

    def crawling_deep(self, uurl):
        page = requests.get(uurl)
        tree = html.fromstring(page.text)
        name = tree.findtext('.//div[@class="sales-info"]/h1')
        phone = tree.findtext('.//p[@class="phone"]')
        try:
            email = tree.xpath('//div[@class="business-card-footer"]/a[@class="email-business"]/@href')[0]
        except IndexError:
            email=""
        print(name, phone, email)


if __name__ == '__main__':
    url = page_crawler.main_link
    crawl = Info_grabber(url)
    crawl.crawler()
    crawl.passing_links()

您会注意到我在page_crawler 中添加了pages 属性和get_pages 方法,我将把实现部分留给您。
稍后您可能需要向page_crawler 添加更多方法,因为如果您开发更多子类,它们可能会派上用场。最后考虑考虑组合,因为它也是一个强大的 OOP 功能。

【讨论】:

  • 我在移动设备上,所以无法查看。你的解决方案总是很摇滚。我一有电脑就会给你反馈。顺便说一句,您的答案永远不需要经过测试才能接受。感谢您的宝贵时间。
  • 我测试了您的代码,发现结果符合我的预期。看来你又能读懂我的心思了。底线是我希望我的 Info_grabber 类通过在两者之间建立一座桥梁来利用 page_crawler 生成的那些链接,你向我展示了如何。再次感谢一万亿先生 t.m.adam。
【解决方案2】:

您的crawl 是页面爬虫类的实例,但不是InfoGrabber 类,后者是具有passing_links 方法的类。我认为您想要做的是让 crawl 成为 InfoGrabber 的一个实例。

那我相信在做 self.crawling_deep 之前你必须做:

if n_link:
    page = requests.get(n_link).text            
    tel = re.findall(r'\d{10}', page)[0] if re.findall(r'\d{10}', page) else ""
    print(tel)

【讨论】:

  • 感谢 Cary Shindell 的回答。在我再次运行时更改了您的建议后,当我在“info_grabber”类中遇到“self.crawling_deep(nlink)”行时,我收到一个新错误“raise MissingSchema(error)”。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-09
  • 1970-01-01
  • 1970-01-01
  • 2016-08-27
相关资源
最近更新 更多