【问题标题】:Unable to scrape all the urls available in different depth out of some json content无法从某些 json 内容中抓取不同深度的所有可用 url
【发布时间】:2021-04-08 15:58:48
【问题描述】:

我正在尝试解析某些 json 内容中不同深度的所有 url 值。我附上a file,其中包含不同深度的网址供您参考。

这是它们的结构(截断):

{'hasSub': True,
 'navigationTitle': 'Products',
 'nodeName': 'products',
 'pages': [{'hasSub': True,
            'navigationTitle': 'Enclosures',
            'nodeName': 'PG0002SCHRANK1',
            'pages': [{'hasSub': True,
                       'navigationTitle': 'Hygienic Design',
                       'nodeName': 'PG0125SCHRANK1',
                       'pages': [{'hasSub': False,
                                  'navigationTitle': 'Hygienic Design Terminal '
                                                     'box HD',
                                  'nodeName': 'PRO0130',
                                  'target': '_self',
                                  'url': '/com-en/products/PG0002SCHRANK1/PG0125SCHRANK1/PRO0130'},
                                 {'hasSub': False,
                                  'navigationTitle': 'Hygienic Design Compact '
                                                     'enclosure HD, '
                                                     'single-door',
                                  'nodeName': 'PRO0131',
                                  'target': '_self',
                                  'url': '/com-en/products/PG0002SCHRANK1/PG0125SCHRANK1/PRO0131'},

如果我考虑以上内容,我所追求的输出:

/com-en/products/PG0002SCHRANK1/PG0125SCHRANK1/PRO0130
/com-en/products/PG0002SCHRANK1/PG0125SCHRANK1/PRO0131

我为生成 json 内容而编写的脚本:

import requests
from pprint import pprint

url = 'https://www.rittal.com/.rest/nav/menu/tree?'
params = {
    'path': 'com',
    'locale': 'en',
    'deep': '10'
}
with requests.Session() as s:
    s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
    s.headers['Accept'] = 'application/json, text/plain, */*'
    r = s.get(url,params=params)
    pprint(r.json()['pages'][0])

如何从 json 内容中抓取不同深度的所有 url?

【问题讨论】:

    标签: python json python-3.x web-scraping


    【解决方案1】:

    您可以做的是对 JSON 进行递归。这是处理不同深度 URL 的最佳方式。

    以下递归将通过对 JSON 进行递归来检索最深的 URL。

    import requests
    from pprint import pprint
    
    url = 'https://www.rittal.com/.rest/nav/menu/tree'
    params = {
        'path': 'com',
        'locale': 'en',
        'deep': '10'
    }
    
    def recurse(data):
        if 'pages' in data:
            for page in data['pages']:
                recurse(page)
        elif 'url' in data and data['url'].startswith('/com-en/'):
            urls.append(data['url'])
    
    urls = []
    with requests.Session() as s:
        s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
        s.headers['Accept'] = 'application/json, text/plain, */*'
        r = s.get(url, params=params).json()
        recurse(r)
        pprint(urls)
    

    这就是它的工作原理:

    • 递归案例 - 如果当前级别有页面,则在当前级别递归每个page
    • 基本情况 - 如果 URL 出现在当前级别,则将其附加到 URL 列表中

    此外,如果您将elif 切换为if,它将为您提供所有任何级别的URL。

    更新:该 JSON 中似乎有 2 个 rouge URL。特别是,一个是https://www.eplan-software.com/solutions/eplan-platform/,另一个是空白!因此,我添加了条件 data['url'].startswith('/com-en/') 以仅附加符合预期模式的 URL。

    【讨论】:

      【解决方案2】:

      好的,我似乎在其他地方找到了一个解决方案,可以从任何嵌套的 json 中获取所有可用的链接。

      import requests
      from pprint import pprint
      
      url = 'https://www.rittal.com/.rest/nav/menu/tree?'
      params = {
          'path': 'com',
          'locale': 'en',
          'deep': '10'
      }
      
      def json_extract(obj, key):
          arr = []
      
          def extract(obj, arr, key):
              if isinstance(obj, dict):
                  for k, v in obj.items():
                      if isinstance(v, (dict, list)):
                          extract(v, arr, key)
                      elif k == key:
                          arr.append(v)
              elif isinstance(obj, list):
                  for item in obj:
                      extract(item, arr, key)
              return arr
      
          values = extract(obj, arr, key)
          return values
      
      with requests.Session() as s:
          s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
          s.headers['Accept'] = 'application/json, text/plain, */*'
          r = s.get(url, params=params).json()
          for item in json_extract(r,'url'):
              print(item)
      

      脚本生成的链接数约为 3500。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多