【问题标题】:How to scrape specific text from specific table elements如何从特定表格元素中抓取特定文本
【发布时间】:2019-07-09 21:07:25
【问题描述】:

我正在尝试从亚马逊产品页面上的特定表格元素中抓取特定文本。

URL_1 包含所有元素 - https://www.amazon.com/dp/B008Q5LXIE/ URL_2 只有“销售排名” - https://www.amazon.com/dp/B001V9X26S

网址_1: “产品详细信息”表有 9 个项目,我只对“产品尺寸”、“运输重量”、项目型号和所有“卖家排名”感兴趣

我无法解析这些项​​目上的文本,因为有些项目位于一个代码块中,而其他项目则没有。

我正在使用 beautifulsoup,我在桌子上运行了 text.strip() 并得到了一切,但非常混乱。我已经尝试过 soup.find('li') 和 text.strip() 来查找单个元素,但是对于卖家排名,它返回的所有 3 个排名在一次返回中混杂在一起。我也尝试过正则表达式来清理文本,但它不适用于 4 个不同的卖家等级。我已经成功使用 Try, except, Pass 方法进行抓取,并且每个格式都采用该格式

A bad example of the code used, I was trying to get sales rank past the </b> 
element in the HTML
#Sales Rank
        sales_rank ='NOT'
        try:
            sr = soup.find('li', attrs={'id':'SalesRank'})
            sales_rank = sr.find('/b').text.strip()
        except:
            pass

我希望能够将列出的元素抓取到字典中。我希望看到结果为

dimensions = 6x4x4
weight = 4.8 ounces
Item_No = IT-DER0-IQDU
R1_NO = 2,036
R1_CAT = Health & Household
R2_NO = 5
R2_CAT = Joint & Muscle Pain Relief Medications
R3_NO = 3
R3_CAT = Naproxen Sodium
R4_NO = 6
R4_CAT = Migraine Relief

my_dict =   {'dimensions':'dimensions','weight':'weight','Item_No':'Item_No', 'R1_NO':R1_NO,'R1_CAT':'R1_CAT','R2_NO':R2_NO,'R2_CAT':'R2_CAT','R3_NO':R3_NO,'R3_CAT':'R3_CAT','R4_CAT':'R4_CAT'}

网址_2: 页面上唯一感兴趣的元素是“销售排名”。 “产品尺寸”、“装运重量”、产品型号不存在。但是,我想要一个类似于 URL_1 的返回值,但缺少的元素的值为“NA”。结果与 URL_1 相同,仅当元素不存在时给出“NA”。通过在 Try/Except 语句之前设置一个值,我已经成功地实现了这一点。例如: Shipping Weight = 'NA' ... 然后运行 ​​try/except: pass ,所以我得到 'NA' 并且我的字典不为空。

【问题讨论】:

    标签: python html web-scraping beautifulsoup


    【解决方案1】:

    您可以在 bs4 4.7.1 中使用 stripped_strings 和 :contains。这感觉就像是为了获得所需的输出格式而费尽心思。当然,有更多 python 经验的人可以减少这种情况并提高其效率。合并取自 @aaronhall 的 dicts 语法。

    import requests
    from bs4 import BeautifulSoup as bs
    import re
    
    links = ['https://www.amazon.com/Professional-Dental-Guard-Remoldable-Customizable/dp/B07L4YHBQ4', 'https://www.amazon.com/dp/B0040ODFK4/?tag=stackoverfl08-20']
    
    for link in links:
    
        r = requests.get(link, headers = {'User-Agent': 'Mozilla\5.0'})
        soup = bs(r.content, 'lxml')
        fields = ['Product Dimensions', 'Shipping Weight', 'Item model number', 'Amazon Best Sellers Rank']
    
        temp_dict = {}
    
        for field in fields:
            element = soup.select_one('li:contains("' + field + '")')
            if element is None:
                temp_dict[field] = 'N/A'
            else:
                if field == 'Amazon Best Sellers Rank':
                    item = [re.sub('#|\(','', string).strip() for string in soup.select_one('li:contains("' + field + '")').stripped_strings][1].split(' in ')
                    temp_dict[field] = item
                else:
                    item = [string for string in element.stripped_strings][1]
                    temp_dict[field] = item.replace('(', '').strip()
    
        ranks = soup.select('.zg_hrsr_rank')
        ladders = soup.select('.zg_hrsr_ladder')
    
        if ranks:
            cat_nos = [item.text.split('#')[1] for item in ranks]
        else:
             cat_nos = ['N/A']
    
        if ladders:                      
            cats = [item.text.split('\xa0')[1] for item in soup.select('.zg_hrsr_ladder')]
        else:
            cats = ['N/A']
    
        rankings = dict(zip(cat_nos, cats))
    
        map_dict = {
            'Product Dimensions': 'dimensions',
            'Shipping Weight': 'weight', 
            'Item model number': 'Item_No',
            'Amazon Best Sellers Rank': ['R1_NO','R1_CAT']
        }
    
        final_dict = {}
    
        for k,v in temp_dict.items():
            if k == 'Amazon Best Sellers Rank' and v!= 'N/A':
                item = dict(zip(map_dict[k],v))
                final_dict = {**final_dict, **item}
            elif k == 'Amazon Best Sellers Rank' and v == 'N/A':
                item = dict(zip(map_dict[k], [v, v]))
                final_dict = {**final_dict, **item}
            else:
                final_dict[map_dict[k]] = v
    
        for k,v in enumerate(rankings):
            #print(k + 1, v, rankings[v])
            prefix = 'R' + str(k + 2) + '_'
            final_dict[prefix + 'NO'] = v  
            final_dict[prefix + 'CAT'] = rankings[v]
    
        print(final_dict)
    

    【讨论】:

    • 哎呀....我应该进一步向下滚动问题,因为我没有看到那一点!我再看看。
    • 您能否提供一个示例 url 是这种情况和预期的输出?
    • 请尝试带有几个网址的底部版本。
    • 没问题。感谢您的反馈:-)
    • 你能提供一个发生这种情况的示例网址吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多