【问题标题】:Scrapy: store all external links and crawl all interal linksScrapy:存储所有外部链接并爬取所有内部链接
【发布时间】:2015-12-31 19:51:51
【问题描述】:

我一直在研究一个从起始 url 爬过所有内部链接并且只收集带有scrapy 的外部链接的scrapy 网络爬虫。但是,我的主要问题是对外部链接和内部链接进行分类。例如,当我尝试过滤掉带有link.startswith("http") or link.startswith("ftp") or link.startswith("www")的外部链接时,如果该网站使用绝对路径(www.my-domain.com/about而不是/about)链接自己的网站,那么即使它是不是。以下是我的代码:

import scrapy
from lab_relationship.items import Links

class WebSpider(scrapy.Spider):
    name = "web"
    allowed_domains = ["my-domain.com"]
    start_urls = (
        'www.my-domain.com',
    )

    def parse(self, response):
        """ finds all external links"""
        items = []
        for link in set(response.xpath('//a/@href').extract()):
            item = Links()
            if len(link) > 1:
                if link.startswith("/") or link.startswith("."):
                    # internal link
                    url = response.urljoin(link)
                    item['internal'] = url
                    #yield scrapy.Request(url, self.parse)
                elif link.startswith("http") or link.startswith("ftp") or link.startswith("www"):
                    # external link
                    item['external'] = link
                else:
                    # misc. links: mailto, id (#)
                    item['misc'] = link
                items.append(item)
        return items

有什么建议吗?

【问题讨论】:

    标签: python web-scraping scrapy scrapy-spider


    【解决方案1】:

    使用link extractor

    实例化时,您必须传递允许的域。您不必担心指定所需的标签,因为(根据文档)参数 tags 默认采用 ('a', 'area')

    在 Rust lang 网站的示例中,打印其域中所有内部链接的代码如下所示:

    import scrapy
    from scrapy.linkextractors import LinkExtractor
    
    
    class RustSpider(scrapy.Spider):
        name = "rust"
        allowed_domains = ["www.rust-lang.org"]
        start_urls = (
            'http://www.rust-lang.org/',
        )
    
        def parse(self, response):
            extractor = LinkExtractor(allow_domains='rust-lang.org')
            links = extractor.extract_links(response)
            for link in links:
                print link.url
    

    输出将是此类链接的列表:https://doc.rust-lang.org/nightly/reference.html(我无法发布更多内容),同时排除所有链接,如 StackOverflow 的链接。

    请务必查看文档页面,因为链接提取器有许多您可能需要的参数。

    【讨论】:

    • 嗯..你是不是建议用LinkExtractor做一组内部链接,并且对于所有链接,检查它们是否与内部链接匹配,如果不匹配,它们是外部链接?
    • 不完全是,通过设置deny_domains='domain',您可以提取不在给定域(外部)中的链接。
    【解决方案2】:

    if 可以有多个 or 语句,而不仅仅是两个。

    【讨论】:

    • 但我的数组也将包含内部链接。我只想要外部链接
    • 是的,刚才注意到了。查看您的代码,“if link.startswith("/") 或 link.startswith("."):" 行可以有多个“或”语句,否则可能使用switch 语句
    • 我已经在我的代码中使用了多个ors,我看不出这将如何从相对链接中过滤掉绝对链接
    • 您知道您的内部域,所以如果链接以内部域开头,是否应该选择任何内部域?即:link.startswith("http://www.my-domain.com/")
    • 主要问题是使用条件语句将 www.my-domain.com 分类为外部和内部链接,而它应该是内部链接。如果是,比如 www.other-domain.com,那么它应该被归类为外部。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 2014-02-25
    • 2016-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多