Python 避免由于相对URL而导致的错误请求
我正在尝试使用Scrapy对网站进行爬网,而我想要删除的每个页面的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链接
<!-- 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