scrapy如何用于提取网站的链接图?

时间:2012-10-09 14:18:37

标签: web-crawler scrapy

给定起始网址start(以及关于可接受域等的一些规则)我想生成一个有向图(V,E),其中V中的节点是可从{{到达的页面} 1}},只要页面start上有指向页面(u,v)的超链接,E中就会出现一个弧u

是否有一种简单的方法可以使用v获取此类图表?如果它可以更容易/更好地实现目标,我也会很高兴使用另一个开源工具。

1 个答案:

答案 0 :(得分:16)

我不知道任何正在产生你想要的东西的工具或贡献。你必须建立一个scrapy蜘蛛。我可以在这里解释一下必要的步骤:

  • 创建scrapy项目并生成默认蜘蛛

    $ scrapy startproject sitegraph
    $ cd sitegraph
    $ scrapy genspider graphspider mydomain.com
    
  • 这将创建一个包含items.py文件的目录。在此文件中添加以下行

    from scrapy.item import Item, Field
    
    class SitegraphItem(Item):
         url=Field()
         linkedurls=Field()
    
  • 在spiders目录中你会发现graphspider.py替换它(当然mydomain.com需要替换):

    from scrapy.selector import HtmlXPathSelector
    from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
    from scrapy.contrib.spiders import CrawlSpider, Rule
    from scrapy.utils.url import urljoin_rfc
    from sitegraph.items import SitegraphItem
    
    class GraphspiderSpider(CrawlSpider):
        name = 'graphspider'
        allowed_domains = ['mydomain.com']
        start_urls = ['http://mydomain/index.html']
    
        rules = (
            Rule(SgmlLinkExtractor(allow=r'/'), callback='parse_item', follow=True),
        )
    
        def parse_item(self, response):
            hxs = HtmlXPathSelector(response)
            i = SitegraphItem()
            i['url'] = response.url
            i['http_status'] = response.status
            llinks=[]
            for anchor in hxs.select('//a[@href]'):
                href=anchor.select('@href').extract()[0]
                if not href.lower().startswith("javascript"):
            llinks.append(urljoin_rfc(response.url,href))
            i['linkedurls'] = llinks
            return i
    
  • 然后编辑settings.py文件并添加(相应地更改文件名):

    FEED_FORMAT="jsonlines"
    FEED_URI="file:///tmp/sitegraph.json"
    
  • 现在你可以运行:

    $ scrapy crawl graphspider
    
  • 这将生成一个可用于构建图形的json文件。

您可以使用像networkx这样的软件包来分析它的pygraphviz来绘制它(不建议用于大型网站)

import json
import pygraphviz as pg

def loadgraph(fname):
        G=pg.AGraph(directed=True)
        for line in open(fname):
            j=json.loads(line)
            url=j["url"]
            G.add_node(url)
            for linked_url in j["linkedurls"]:
                G.add_edge(url,linked_url)
        return G

if __name__=='__main__':
        G=loadgraph("/tmp/sitegraph.json")
        G.layout(prog='dot')
        G.draw("sitegraph.png")