【问题标题】:Crawl a website and its external links recursively to create a graph for a data analysis project n Python递归地爬取网站及其外部链接,为数据分析项目创建图表 n Python
【发布时间】:2017-11-25 18:28:39
【问题描述】:

我有一个项目,我正在尝试将其组合在一起进行数据分析实验。我有一个管道,但我不完全知道如何继续获取我需要的数据。 我想爬取一个网站并找到所有内部和外部链接,将它们分开并递归地爬取外部链接,直到达到一定深度。我想这样做来创建一个网站所有连接的图表,然后使用中心性算法找到中心节点并从那里继续。 理想情况下,我想在这个项目中使用 python 2。 我查看了 scrapy、beautiful soup 和其他库,但都非常混乱。

任何关于抓取和创建图表的帮助和/或建议将不胜感激

谢谢

编辑:

我正在尝试实施您建议的解决方案,使用下面的代码,我可以在调试信息中看到它正在查找链接,但它们没有保存在 LinkList 类中,或者我提取错误他们正在被过滤。

有什么建议吗?

class LinkList(Item):
    url = Field()

class WebcrawlerSpider(CrawlSpider):
    name = 'webcrawler'
    allowed_domains = ['https://www.wehiweb.com']
    start_urls = ['https://www.wehiweb.com']

rules = (
    Rule(LxmlLinkExtractor(allow=()), callback='parse_obj', follow=True),
)

def parse_obj(self,response):
    item = LinkList()
    item['url'] = []
    for link in LxmlLinkExtractor(allow=(),deny = self.allowed_domains).extract_links(response):
        item['url'].append(link.url)
        yield item

def main():
    links = LinkList()
    process = CrawlerProcess()
    process.crawl(WebcrawlerSpider)
    process.start()
    print(links.items())

if __name__ == "__main__":
    main()

【问题讨论】:

    标签: python beautifulsoup scrapy web-crawler scrapy-spider


    【解决方案1】:

    Scrapy 应该可以正常工作。大多数人使用它从网站中提取数据(抓取),但它也可以用于简单的抓取。

    在 scrapy 中,您有爬取网站和跟踪链接的蜘蛛。一个 scrapy 项目可以包含许多蜘蛛,但在标准设置中,每个蜘蛛都有自己的队列并执行自己的任务。

    正如您描述的用例,我推荐两个独立的scrapy spider:

    • 一个用于现场抓取,仅针对该域设置 allowed_domains 和非常高甚至 0 (=infinite) MAX_DEPTH 设置,以便抓取整个域
    • 一个用于异地抓取,带有一个空的allowed_domains(将允许所有域)和一个较低的MAX_DEPTH 设置,这样它将在一定数量的跃点后停止

    从您的parse 方法的角度来看,scrapy 有RequestItem 的概念。您可以从解析响应的方法中返回 RequestItem

    • 请求将触发 scrapy 访问网站,然后在结果上调用您的 parse 方法
    • items 允许您指定为项目定义的结果

    因此,无论何时您想关注一个链接,您都会从您的 parse 方法中 yield 一个 Request。对于您项目的所有结果,您将获得Item

    在你的情况下,我会说你的 Item 是这样的:

    class LinkItem(scrapy.Item):
        link_source = scrapy.Field()
        link_target = scrapy.Field()
    

    如果您在页面http://example.com/ 并找到指向/subsite 的链接,这将允许您返回项目link_source="http://example.com/", link_target="http://example.com/subsite"

    def parse(self, response):
        # Here: Code to parse the website (e.g. with scrapy selectors 
        # or beautifulsoup, but I think scrapy selectors should
        # suffice
    
        # after parsing, you have a list "links"
        for link in links:
            yield Request(link)  # make scrapy continue the crawl
    
            item = LinkItem()
            item['link_source'] = response.url
            item['link_target'] = link
            yield item  # return the result we want (connections in link graph)
    

    您可能会看到我没有进行任何深度检查等。您不必在 parse 方法中手动执行此操作,scrapy 附带 Middleware。其中一个中间件称为OffsiteMiddleware,它将检查您的蜘蛛是否被允许访问特定域(使用选项allowed_domains,查看scrapy 教程)。另一个是DepthMiddleware(也可以查看教程)。

    这些结果可以写在你想要的任何地方。 Scrapy 附带一个名为feed exports 的东西,它允许您将数据写入文件。如果您需要更高级的东西,例如一个数据库,可以看scrapy的Pipeline

    我目前认为除了 scrapy 之外不需要其他库和项目来收集数据。

    当然,当您想要处理数据时,您可能需要专门的数据结构而不是纯文本文件。

    【讨论】:

    • 非常感谢!我将建立一个完整的scrapy项目并尝试实施你所说的。我真的很感谢你的帮助:)顺便说一句,我投了赞成票,但没有足够的声誉来展示:)