python - sirve - scrapear web
Crear bucle para analizar datos de tabla en scrapy/python (2)
Haga que python script use scrapy, que raspa los datos de un sitio web, lo asigna a 3 campos y luego genera un .csv. Funciona bien, pero con un problema importante. Todos los campos contienen todos los datos, en lugar de separarlos para cada fila de la tabla. Estoy seguro de que esto se debe a que mi bucle no funciona y cuando encuentra el xpath solo toma todos los datos de cada fila antes de continuar para obtener datos para los otros 2 campos, en lugar de crear filas separadas
def parse(self, response):
hxs = HtmlXPathSelector(response)
divs = hxs.select(''//tr[@class="someclass"]'')
for div in divs:
item = TestBotItem()
item[''var1''] = div.select(''//table/tbody/tr[*]/td[2]/p/span[2]/text()'').extract()
item[''var2''] = div.select(''//table/tbody/tr[*]/td[3]/p/span[2]/text()'').extract()
item[''var3''] = div.select(''//table/tbody/tr[*]/td[4]/p/text()'').extract()
return item
El tr con * aumenta en número con cada entrada en el sitio web que necesito rastrear, y las otras dos rutas se insertan a continuación. ¿Cómo edito esto para que tome el primer conjunto de datos para decir // table / tbody / tr [3] solamente, lo almacene para los tres campos y luego pase a // table / tbody / tr [4] etc.? ?
Actualizar
Funciona correctamente, sin embargo, estoy tratando de agregar algo de validación al archivo pipelines.py para eliminar cualquier registro donde var1 sea más del 100%. Estoy seguro de que mi código a continuación es incorrecto, y también "cede" en lugar de "devolver", ¿detiene la tubería que se utiliza?
from scrapy.exceptions import DropItem
class TestbotPipeline(object):
def process_item(self, item, spider):
if item(''var1'') > 100%:
return item
else:
raise Dropitem(item)
Creo que esto es lo que estás buscando:
def parse(self, response):
hxs = HtmlXPathSelector(response)
divs = hxs.select(''//tr[@class="someclass"]'')
for div in divs:
item = TestBotItem()
item[''var1''] = div.select(''./td[2]/p/span[2]/text()'').extract()
item[''var2''] = div.select(''./td[3]/p/span[2]/text()'').extract()
item[''var3''] = div.select(''./td[4]/p/text()'').extract()
yield item
Usted realiza un bucle en los tr
s y luego usa las expresiones relativas de XPath ( ./td...
), y en cada iteración utiliza la instrucción yield
.
También puede agregar cada elemento a una lista y devolver esa lista fuera del ciclo) de esta manera (es equivalente al código anterior):
def parse(self, response):
hxs = HtmlXPathSelector(response)
divs = hxs.select(''//tr[@class="someclass"]'')
items = []
for div in divs:
item = TestBotItem()
item[''var1''] = div.select(''./td[2]/p/span[2]/text()'').extract()
item[''var2''] = div.select(''./td[3]/p/span[2]/text()'').extract()
item[''var3''] = div.select(''./td[4]/p/text()'').extract()
items.append(item)
return items
No necesita HtmlXPathSelector
. Scrapy ya tiene un selector XPATH incorporado. Prueba esto:
def parse(self, response):
divs = response.xpath(''//tr[@class="someclass"]'')
for div in divs:
item = TestBotItem()
item[''var1''] = div.xpath(''table/tbody/tr[*]/td[2]/p/span[2]/text()'').extract()[0]
item[''var2''] = div.xpath(''table/tbody/tr[*]/td[3]/p/span[2]/text()'').extract()[0]
item[''var3''] = div.xpath(''table/tbody/tr[*]/td[4]/p/text()'').extract()[0]
return item