首页 > 解决方案 > 如何将多个抓取的网址转换为单个观察?

问题描述

我目前正在搜寻一家在线商店以收集其所有产品的数据。这包括每个产品具有的多个图像的 URL。到目前为止的代码如下:

for image in subsoup.find_all('a',{'class':'thumb-link'}):
  url.append(image.find('img').get('src'))

这会生成单个产品的 url 列表,然后将其添加到字典键中:

'URL': ['url1', 'url2', 'url3', 'url4']

我想知道的是如何将每个产品的多个链接变成一个单独的观察,只占据一行。这样,当我将字典转换为 DataFrame 并将其导出为 csv 时,所有列将具有相同的长度。

这是当前的输出:

| Name                |      URL        |     Price     |
| --------            | --------------  |-------------- |
| Wesson, aceite      |  'url1'         |     10.99     |
|                     |  'url2'         |               |
|                     |  'url3'         |               |
|                     |  'url4'         |               |

这是我期望的那种输出:

| Name                |      URL                           |Price         |
| --------            | --------------                     |--------------
| Wesson, aceite      | ['url1', 'url2', 'url3', 'url4']   |10.99          |

标签: pythonweb-scrapingbeautifulsoup

解决方案


我不确定这是包含您的 url 的最佳格式。我很想每行有一个图像 url 并重复其他信息。

但是,对于您想要的格式,您可以简单地在最后转换为数据框的列表列表。给定行的 URL 列将是您的 urls 列表。您可以使用辅助函数为给定的 url 返回一行并将其附加到全局列表以在末尾转换为 df 例如

我只使用了一个类别来获取一些测试链接。如果对于所有产品,我会首先循环页面、产品等,收集所有产品页面链接,然后访问这些链接以获取信息。

由于这可能涉及很多链接,您需要开发错误处理、暂停、重试等。

import requests
from bs4 import BeautifulSoup as bs
import pandas as pd

def get_row(soup):
    images = [i['src'] for i in soup.select('.product-thumb-item-img')]
    price = soup.select_one('.priceValue').text.strip()
    title = soup.select_one('#product-display-name').text.strip().replace(u'\xa0', ' ')
    return [title, images, price]


results = []
base = 'https://www.pricesmart.com'

with requests.Session() as s:
    test_soup = bs(s.get('https://www.pricesmart.com/site/sv/es/categoria/alimentos?cat=G10D03009').text, 'lxml')
    test_links = [base + i['href'] for i in test_soup.select('.search-product-box a')]
    
    for link in test_links:
        try: 
            r = s.get(link)
            soup = bs(r.content, 'lxml')
            results.append(get_row(soup))
        except:
            print(r, link) 'for initial debugging. You may want to test status code etc... add appropriate error handling
            break
            
df = pd.DataFrame(results, columns = ['Title', 'Url', 'Price'])

推荐阅读