Python 避免由于相对URL而导致的错误请求

Python 避免由于相对URL而导致的错误请求,python,scrapy,web-crawler,Python,Scrapy,Web Crawler,我正在尝试使用Scrapy对网站进行爬网,而我想要删除的每个页面的URL都是使用这种相对路径编写的: <!-- on page https://www.domain-name.com/en/somelist.html (no <base> in the <head>) --> <a href="../../en/item-to-scrap.html">Link</a> 基本上,scrapy通过加入currenturl和废弃的url链接

我正在尝试使用Scrapy对网站进行爬网,而我想要删除的每个页面的URL都是使用这种相对路径编写的:

<!-- on page https://www.domain-name.com/en/somelist.html (no <base> in the <head>) -->
<a href="../../en/item-to-scrap.html">Link</a>

基本上,scrapy通过加入currenturl和废弃的url链接来获取下一个url。如果您加入您作为示例提到的URL

<!-- on page https://www.domain-name.com/en/somelist.html -->
<a href="../../en/item-to-scrap.html">Link</a>
urljoin行为似乎是有效的。见:

如果可能的话,你能通过你正在爬行的网站吗

有了这样的理解,解决方案可以是

1) 操纵URL(删除这两个点和斜线)。在爬行蜘蛛中生成。基本上覆盖解析或_请求_到_folow

爬行蜘蛛的来源:

2) 在downloadmiddleware中操纵url,这可能会更干净。在下载中间件的进程_请求中删除../

下载中间件的文档:

3) 使用基本爬行器并返回要进一步爬网的已处理url请求

basespider的文档:


如果你有任何问题,请告诉我

多亏了你,我终于找到了解决办法。我使用的流程链接如下:

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import HtmlXPathSelector
from scrapy.item import Item, Field

class Product(Item):
    name = Field()

class siteSpider(CrawlSpider):
    name = "domain-name.com"
    allowed_domains = ['www.domain-name.com']
    start_urls = ["https://www.domain-name.com/en/"]
    rules = (
        Rule(SgmlLinkExtractor(allow=('\/en\/item\-[a-z0-9\-]+\-scrap\.html')), process_links='process_links', callback='parse_item', follow=True),
        Rule(SgmlLinkExtractor(allow=('')), process_links='process_links', follow=True),
    )

    def parse_item(self, response):
        x = HtmlXPathSelector(response)
        product = Product()
        product['name'] = ''
        name = x.select('//title/text()').extract()
        if type(name) is list:
            for s in name:
                if s != ' ' and s != '':
                    product['name'] = s
                    break
        return product

    def process_links(self,links):
        for i, w in enumerate(links):
            w.url = w.url.replace("../", "")
            links[i] = w
        return links

谢谢你的帮助。我正在尝试实施你的第二个解决方案,到目前为止行为没有改变。我相信我的中间件根本没有被调用,或者什么也不做。我找不到任何process_request()实现的示例,文档也不清楚process_request应该做什么(例如,如果我返回一个请求会发生什么?)请参阅我编辑的问题,以了解您的后续回答。我认为您不需要返回请求。只需更改url即可。我同意文档没有提到返回请求时的行为。很抱歉,我更改了方法以返回父方法的结果,并使用更正的url。我相信这应该能奏效。现在我的问题是,当我运行爬行器爬网时,我的自定义下载程序没有出现在启用的下载程序中间件列表中。(参见问题)我可能没有正确添加它。我认为DownloadMiddleWare类不存在。你的自定义下载中间件不需要继承任何类。好吧,我的错,我写了下载中间件而不是下载中间件。测试。
<!-- on page https://www.domain-name.com/en/somelist.html -->
<a href="../../en/item-to-scrap.html">Link</a>
import urlparse 
urlparse.urljoin("https://www.domain-name.com/en/somelist.html","../../en/item-to-scrap.html")
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import HtmlXPathSelector
from scrapy.item import Item, Field

class Product(Item):
    name = Field()

class siteSpider(CrawlSpider):
    name = "domain-name.com"
    allowed_domains = ['www.domain-name.com']
    start_urls = ["https://www.domain-name.com/en/"]
    rules = (
        Rule(SgmlLinkExtractor(allow=('\/en\/item\-[a-z0-9\-]+\-scrap\.html')), process_links='process_links', callback='parse_item', follow=True),
        Rule(SgmlLinkExtractor(allow=('')), process_links='process_links', follow=True),
    )

    def parse_item(self, response):
        x = HtmlXPathSelector(response)
        product = Product()
        product['name'] = ''
        name = x.select('//title/text()').extract()
        if type(name) is list:
            for s in name:
                if s != ' ' and s != '':
                    product['name'] = s
                    break
        return product

    def process_links(self,links):
        for i, w in enumerate(links):
            w.url = w.url.replace("../", "")
            links[i] = w
        return links