【问题标题】:Xpath is correct but no result after scrapingXpath 是正确的,但抓取后没有结果
【发布时间】:2019-06-27 16:58:45
【问题描述】:

我正在尝试抓取以下网站的所有城市名称: https://www.zomato.com/directory.

我尝试使用以下 xpath。

python
#1st approach:
def parse(self,response):
    cities_name = response.xpath('//div//h2//a/text()').extract_first()
    items['cities_name'] = cities_name
    yield items 
 #2nd approach:

def parse(self,response):
 for city in response.xpath("//div[@class='col-l-5 col-s-8 item pt0 pb5 
   ml0']"):
        l = ItemLoader(item = CountryItem(),selector = city)
        l.add_xpath("cities_name",".//h2//a/text()")
        yield l.load_item()
        yield city

实际结果:抓取 0 个页面并抓取 0 个项目
预计:阿德莱德、巴拉瑞特等

【问题讨论】:

    标签: xpath web-scraping scrapy


    【解决方案1】:

    首先要注意:
    您的 xpath 有点太具体了。 html 中的 Css 类并不总是具有可靠的顺序。 class1 class2 最终可能会变成 class2 class1,甚至可能涉及一些语法错误,例如尾随空格:class1 class2

    当您将 xpath 直接匹配到 [@class="class1 class2"] 时,它很有可能会失败。相反,您应该尝试使用contains 函数。

    第二:
    您的cities_name xpath 中有一个小错误。在 html 正文中它的 a>h2> 文本和在你的代码中它被颠倒了 h2>a>text

    也就是说,我设法让它与这些 css 和 xpath 选择器一起工作:

    $ parsel "https://www.zomato.com/directory"                                                                           
    > p.mb10>a>h2::text +first                                                                                            
    Adelaide
    > p.mb10>a>h2::text +len                                                                                              
    736
    > -xpath                                                                                                              
    switched to xpath
    > //p[contains(@class,"mb10")]/a/h2/text() +first                                                                     
    Adelaide
    > //p[contains(@class,"mb10")]/a/h2/text() +len                                                                       
    736
    

    parselcli - https://github.com/Granitosaurus/parsel-cli

    【讨论】:

    • //p[contains(@class,"mb10")]/a/h2/text() +first 是整个xpath?
    • 不,+first 位是 parselcli 处理器语法 - 仅打印第一个结果。 xpath 是一切,直到那一点://p[contains(@class,"mb10")]/a/h2/text()
    【解决方案2】:

    你有一个错误的 XPath:

    def parse(self,response):
     for city_node in response.xpath("//h2"):
            l = ItemLoader(item = CountryItem(), selector = city_node)
            l.add_xpath("city_name", ".//a/text()")
            yield l.load_item()
    

    【讨论】:

      【解决方案3】:

      您没有从该页面获得任何结果的主要原因是该站点的 html 元素格式不正确。您可以使用html5lib 解析器获取结果。我尝试了不同的解析器,但我刚才提到的那个成功了。以下是如何做到这一点。不过,我使用了 css 选择器。

      import scrapy
      from bs4 import BeautifulSoup
      
      class ZomatoSpider(scrapy.Spider):
          name = "zomato"
      
          start_urls= ['https://www.zomato.com/directory']
      
          def parse(self, response):
              soup = BeautifulSoup(response.text, 'html5lib')
              for item in soup.select(".row h2 > a"):
                  yield {"name":item.text}
      

      【讨论】:

      • 我需要在 item.py 中设置什么吗?
      • 什么都没有。照原样运行。
      • 有效!我不熟悉 html..我怎么知道它是否格式正确?因为当我在网络中传递那些 xpath 时它工作正常..
      • 当您看到您要查找的内容在页面源中可用但您的解析器无法挖掘它们时,您可以尝试使用这些解析器html.parserlxmlhtml5lib检查在这种情况下哪个在工作。我对 html 也不是很熟悉,所以我尝试使用上面描述的方法。谢谢。
      猜你喜欢
      • 2014-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 1970-01-01
      相关资源
      最近更新 更多