import requests
import csv
from bs4 import BeautifulSoup 
def cpap_spider(max_pages):
    page=1
    while page<=max_pages:
        url= "https://www.1800cpap.com/cpap-masks/nasal?page=" +str(page)
        source_code= requests.get(url)
        plain_text= source_code.text
        soup= BeautifulSoup(plain_text, 'html.parser')
        for link in soup.findAll("a", {"class":"facets-item-cell-grid-title"}):
            
            href="https://www.1800cpap.com"+link.get("href")
            title= link.string
            each_item(href)
            print(href)
            #print(title)
        page+=1
        
data=[] 
def each_item(item_url):
    source_code= requests.get(item_url)
    plain_text= source_code.text
    soup= BeautifulSoup(plain_text, 'html.parser')
    table=soup.find("table", {"class":"table"})
    
    table_rows= table.find_all('tr')
    for row in table_rows:
        cols = row.find_all('td')
        cols = [ele.text.strip() for ele in cols]
        data.append([ele for ele in cols if ele]) # Get rid of empty values
    b = open('all_appended.csv', 'w')
    a = csv.writer(b)
    a.writerows(data)
    b.close()
    
    
            
cpap_spider(1)            

Este código agrega todas las tablas, una tras otra. Sin embargo, quería una sola tabla grande con encabezados únicos en la primera fila y los valores correspondientes de los productos en el orden secuencial.

3
huy 26 jun. 2020 a las 10:16

2 respuestas

La mejor respuesta

Use xlsxwriter en lugar de csv porque si un texto contiene una sola coma sin espacio al lado "," en lugar de una coma con espacio al lado ", ", entonces su archivo csv se cerrará problemas porque cada valor de columna está separado por "," por ejemplo si text = "aa,bb" entonces csv pensará que este texto contiene dos columnas como "aa" y "bb".

Eso es lo que necesitas

import requests
import xlsxwriter
from bs4 import BeautifulSoup 
def cpap_spider(max_pages):
    global row_i
    page=1
    while page<=max_pages:
        url= "https://www.1800cpap.com/cpap-masks/nasal?page=" +str(page)
        source_code= requests.get(url)
        plain_text= source_code.text
        soup= BeautifulSoup(plain_text, 'html.parser')
        for link in soup.findAll("a", {"class":"facets-item-cell-grid-title"}):
            href="https://www.1800cpap.com"+link.get("href")
            title = link.string
            worksheet.write(row_i, 0, title)
            each_item(href)
            print(href)
            #print(title)
        page+=1

def each_item(item_url):
    global cols_names, row_i
    source_code= requests.get(item_url)
    plain_text= source_code.text
    soup= BeautifulSoup(plain_text, 'html.parser')
    table=soup.find("table", {"class":"table"})
    table_rows= table.find_all('tr')
    for row in table_rows:
      cols = row.find_all('td')
      for ele in range(0,len(cols)):
        temp = cols[ele].text.strip()
        if temp:
          # Here if you want then you can remove unwanted characters like : ? from temp
          # For example "Actual Weight" and ""
          if temp[-1:] == ":":
            temp = temp[:-1]
          # Name of column
          if ele == 0:
            try:
              cols_names_i = cols_names.index(temp)
            except:
              cols_names.append(temp)
              cols_names_i = len(cols_names) -  1
              worksheet.write(0, cols_names_i + 1, temp)
              continue;
          worksheet.write(row_i, cols_names_i + 1, temp)      
    row_i += 1
    
cols_names=[]
cols_names_i = 0
row_i = 1
workbook = xlsxwriter.Workbook('all_appended.xlsx')
worksheet = workbook.add_worksheet()
worksheet.write(0, 0, "Title")
    
cpap_spider(1)
#each_item("https://www.1800cpap.com/viva-nasal-cpap-mask-by-3b-medical")       
workbook.close()
0
Navpreet Devpuri 26 jun. 2020 a las 09:21

Suponiendo que los encabezados son consistentemente la primera fila de cada tabla, solo tiene que omitir esa fila en todas las tablas menos en la primera. Una manera simple de hacerlo es almacenar la primera fila para procesar en una variable inicializada en 0 y establecerla en 1 en la función de procesamiento. Código posible:

def cpap_spider(max_pages):
    page=1
    start_row = 0
    while page<=max_pages:
        ...
        for link in soup.findAll("a", {"class":"facets-item-cell-grid-title"}):
            ...
            each_item(href, start_row)
            start_row = 1        # only first call to each_item will get start_row=1
            print(href)
            #print(title)
        page+=1
...
def each_item(item_url, start_row):
    ...    
    table_rows= table.find_all('tr')
    for row in table_rows[start_row:]:        # skip first row if start_row==1
        ...
0
Serge Ballesta 26 jun. 2020 a las 07:31