Scrapy:跳过缺少方案的hrefs

时间:2014-02-13 20:36:49

标签: python web-crawler scrapy

所以我正在尝试抓取popular.ebay.com页面,我得到error:Missing scheme in request url: #mainContent#锚链接。

以下是我的代码:

def parse_links(self, response):
    hxs = HtmlXPathSelector(response)
    links = hxs.select('//a')
    #domain = 'http://popular.ebay.com/'
    for link in links:
        anchor_text = ''.join(link.select('./text()').extract())
        title = ''.join(link.select('./@title').extract())
        url = ''.join(link.select('./@href').extract())
        meta = {'title':title,}
        meta = {'anchor_text':anchor_text,}
        yield Request(url, callback = self.parse_page, meta=meta,)

我无法将基本网址添加到#mainContent,因为它会使用完整网址方案向网址添加双重网址。我最终获得了这样的网址http://popular.ebay.comhttp://www.ebay.com/sch/i.html?_nkw=grande+mansion

def parse_links(self, response):
    hxs = HtmlXPathSelector(response)
    links = hxs.select('//a')
    #domain = 'http://popular.ebay.com/'
    for link in links:
        anchor_text = ''.join(link.select('./text()').extract())
        title = ''.join(link.select('./@title').extract())
        url = ''.join(link.select('./@href').extract())
        meta = {'title':title,}
        meta = {'anchor_text':anchor_text,}
        yield Request(response.url, callback = self.parse_page, meta=meta,)

我想要获得的链接如下所示:<a href="http://popular.ebay.com/antiques/antique-chair/antique-chairs.htm" title="Antique Chairs">Antique Chairs | </a>但是我得到了这样的链接的错误原因:<a id="gh-hdn-stm" class="gh-acc-a" href="#mainContent">Skip to main content</a>

我如何将基本网址添加到只有哈希锚点链接,或忽略没有基本网址的链接?对于一个简单的解决方案,我尝试了设置规则deny=(#mainContent)restrict_xpaths,但抓取工具仍然会发出相同的错误。

3 个答案:

答案 0 :(得分:1)

error:Missing scheme in request url: #mainContent是由于请求没有方案的网址(网址的“http://”部分)引起的。

#mainContent是一个内部链接,指的是id为“mainContent”的HTML元素。您可能不想关注这些链接,因为它只链接到您当前页面的不同部分。

我建议查看文档http://doc.scrapy.org/en/latest/topics/link-extractors.html#scrapy.contrib.linkextractors.sgml.SgmlLinkExtractor的这一部分。您可以告诉Scrapy遵循符合特定格式的链接,并限制它将从中获取链接的页面部分。记下“restrict_xpaths”和“allow”参数。

希望这会有所帮助:)

答案 1 :(得分:1)

for循环中:

meta = {'anchor_text':anchor_text,}
url = link.select('./@href').extract()[0]
if not '#' in url: // or if url[0] != '#'
    yield Request(response.url, callback = self.parse_page, meta=meta,)

这样可以避免将#foobar作为网址。您可以在#foobar语句中将基本网址添加到else,但由于这会重定向到scrapy已经删除的页面,我认为其中没有一点。

答案 2 :(得分:0)

我发现#mainContent以外的链接缺少方案,所以使用@Robin的逻辑我确保url在parse_page之前包含了基本URL。

    for link in links:
        anchor_text = ''.join(link.select('./text()').extract())
        title = ''.join(link.select('./@title').extract())
        url = ''.join(link.select('./@href').extract())
        meta = {'title':title,}
        meta = {'anchor_text':anchor_text,}
        if domain in url:
            yield Request(url, callback = self.parse_page, meta=meta,)