python - follow - scrapy-análisis de elementos que están paginados
scrapy python documentation (3)
Puede haber dos casos de uso para ''elementos de análisis desechados que están paginados''.
UNA). Solo queremos desplazarnos por la tabla y buscar datos. Esto es relativamente sencillo.
class TrainSpider(scrapy.Spider):
name = "trip"
start_urls = [''somewebsite'']
def parse(self, response):
'''''' do something with this parser ''''''
next_page = response.xpath("//a[@class=''next_page'']/@href").extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.Request(next_page, callback=self.parse)
Observa las últimas 4 líneas. aquí
- Obtenemos el formulario de enlace de la siguiente página xpath de la página siguiente desde el botón de paginación "Siguiente".
- Si es condición para comprobar si no es el final de la paginación.
- Únase a este enlace (que obtuvimos en el paso 1) con la url principal usando url join
- Una llamada recursiva al método
parse
call back.
B) No solo queremos movernos a través de las páginas, sino que también queremos extraer datos de uno o más enlaces en esa página.
class StationDetailSpider(CrawlSpider):
name = ''train''
start_urls = [someOtherWebsite]
rules = (
Rule(LinkExtractor(restrict_xpaths="//a[@class=''next_page'']"), follow=True),
Rule(LinkExtractor(allow=r"/trains//d+$"), callback=''parse_trains'')
)
def parse_trains(self, response):
''''''do your parsing here''''''
En cualquier lugar, observe que:
Estamos utilizando la subclase
CrawlSpider
de la clase principalscrapy.Spider
Nos hemos puesto a ''Reglas''
a) La primera regla, solo verifica si hay una ''próxima_página'' disponible y la sigue.
b) La segunda regla solicita todos los enlaces en una página que están en el formato, digamos
/trains/12343
y luego llama aparse_trains
para realizar y analizar la operación.Importante : tenga en cuenta que no queremos utilizar el método de
parse
regular aquí, ya que estamos utilizando la subclaseCrawlSpider
. Esta clase también tiene un método deparse
por lo que no queremos anularlo. Solo recuerde nombrar su método de devolución de llamada de otra manera que no seaparse
.
Tengo un url de la forma:
example.com/foo/bar/page_1.html
Hay un total de 53 páginas, cada una de ellas tiene ~ 20 filas.
Básicamente quiero obtener todas las filas de todas las páginas, es decir, ~ 53 * 20 elementos.
Tengo un código de trabajo en mi método de análisis, que analiza una sola página, y también va una página más por artículo, para obtener más información sobre el artículo:
def parse(self, response):
hxs = HtmlXPathSelector(response)
restaurants = hxs.select(''//*[@id="contenido-resbus"]/table/tr[position()>1]'')
for rest in restaurants:
item = DegustaItem()
item[''name''] = rest.select(''td[2]/a/b/text()'').extract()[0]
# some items don''t have category associated with them
try:
item[''category''] = rest.select(''td[3]/a/text()'').extract()[0]
except:
item[''category''] = ''''
item[''urbanization''] = rest.select(''td[4]/a/text()'').extract()[0]
# get profile url
rel_url = rest.select(''td[2]/a/@href'').extract()[0]
# join with base url since profile url is relative
base_url = get_base_url(response)
follow = urljoin_rfc(base_url,rel_url)
request = Request(follow, callback = parse_profile)
request.meta[''item''] = item
return request
def parse_profile(self, response):
item = response.meta[''item'']
# item[''address''] = figure out xpath
return item
La pregunta es, ¿cómo rastro cada página?
example.com/foo/bar/page_1.html
example.com/foo/bar/page_2.html
example.com/foo/bar/page_3.html
...
...
...
example.com/foo/bar/page_53.html
Puede usar CrawlSpider en lugar de BaseSpider y usar SgmlLinkExtractor para extraer las páginas de la paginación.
Por ejemplo:
start_urls = ["www.example.com/page1"]
rules = ( Rule (SgmlLinkExtractor(restrict_xpaths=(''//a[@class="next_page"]'',))
, follow= True),
Rule (SgmlLinkExtractor(restrict_xpaths=(''//div[@class="foto_imovel"]'',))
, callback=''parse_call'')
)
La primera regla le dice a scrapy que siga el enlace contenido en la expresión xpath, la segunda regla le dice a scrapy que llame a parse_call a los enlaces contenidos en la expresión xpath, en caso de que quiera analizar algo en cada página.
Para obtener más información, consulte el doc: http://doc.scrapy.org/en/latest/topics/spiders.html#crawlspider
Tienes dos opciones para resolver tu problema. El general es usar el yield
para generar nuevas solicitudes en lugar de return
. De esa manera, puede emitir más de una nueva solicitud desde una sola devolución de llamada. Consulte el segundo ejemplo en http://doc.scrapy.org/en/latest/topics/spiders.html#basespider-example .
En su caso, probablemente haya una solución más simple: simplemente genere la lista de urs de inicio a partir de un patrón como este:
class MySpider(BaseSpider):
start_urls = [''http://example.com/foo/bar/page_%s.html'' % page for page in xrange(1,54)]