如何使用惰性加载器对要加载的图像进行爬网

时间:2019-05-01 19:23:51

标签: ajax web-scraping scrapy

我正在尝试从某个站点抓取图像,并且能够抓取来自html的图像,但不能抓取来自API调用的图像。我通过“网络”标签了解了一些想法,但是却一无所获。

我在另一个直接为我提供json格式和api而不是this site的网站上实现了这一目标

import scrapy
import datetime
import json
from scrapylearning.items import rphotos

class Zomatosphotos(scrapy.Spider):
    name = "Photos"

    def parse(self, response):
        url = response.request.url
        formed_url = url + '?category=food'
            yield scrapy.Request(
                url=formed_url,
                callback=self.parse_url,
            )

    def parse_url(self, response):
        image_section = response.xpath('//div[@class="photos_container_load_more inlineblock w100"]')
        for thumbnails in image_section.xpath('//div[@class="photobox pos-relative left mb10 js-heart-container thumbContainer"]/a'):
            image_thumbnail_url = thumbnails.xpath('@href').get()
            yield scrapy.Request(
                url=image_thumbnail_url,
                callback=self.parse_image,
            )

    def parse_image(self, response):
        item = photos()
        image_urls = []
        scroll_image = response.xpath('//div[@class="col-s-16 ui segment"]/div/img')
        image_url = scroll_image.xpath("@src").extract_first()
        name = response.xpath('//div[@class="photov__header clearfix mbot0"]/h1/text()').get().strip("'s photo")
        image_urls.append(image_url)

        item['image_urls'] = image_urls

        return item

    def start_requests(self):
        urls = [
            'https://www.zomato.com/new-york-city/waldys-wood-fired-pizza-penne-chelsea-manhattan/photos'
        ]

        for url in urls:
            yield scrapy.Request(url=url,
                                 callback=self.parse,
                                 )

我只需要加载更多图像部分的图像。谢谢您的支持。 这是我的items.py文件代码

class photos(scrapy.Item):
    image_urls = scrapy.Field()

1 个答案:

答案 0 :(得分:0)

在第https://www.yelp.com/biz_photos/ess-a-bagel-new-york页上,HTML中没有任何photos_container_load_more。而且它不使用任何API。

我看到HTML中小图片的网址-即。

  

s3-media3.fl.yelpcdn.com/bphoto/uAw2llFfNfVEh2auVDtXyg/258s.jpg

如果我将258s.jpg的最后一部分更改为o.jpg,那么我会得到很大的印象。

代码可以正常工作,而无需创建项目。您可以复制到文件script.py并运行python script.py

import scrapy

class MySpider(scrapy.Spider):

    name = 'myspider'

    def start_requests(self):
        urls = ['https://www.yelp.com/biz_photos/ess-a-bagel-new-york']

        for url in urls:
            url = url + '?category=food'
            yield scrapy.Request(url=url, callback=self.parse)


    def parse(self, response):
        # small versions
        images = response.xpath('//img[@class="photo-box-img"]/@src ').extract()
        #yield {'image_urls': images}

        # big versions
        images = [url.replace('258s.jpg', 'o.jpg') for url in images]
        yield {'image_urls': images}

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    #'USER_AGENT': 'Mozilla/5.0',
    'ITEM_PIPELINES': {'scrapy.pipelines.images.ImagesPipeline': 1},
    'IMAGES_STORE': '.',
})

c.crawl(MySpider)
c.start()

编辑zomato.com的代码

我使用不同的url,因为它具有30多个图像,我可以测试parse_post

我将FormRequestdata一起使用,以获取HTML,其中包含当您单击“加载更多”时加载的图像。

它可以加载10张新图像,但是您可以使用limit一次加载更多图像。

使用offset可以获取下10张图像。

res_id在不同的地方有所不同。您可以在每个图片网址中找到它。我没有检查这个数字是否在HTML中。

如果您有缩略图(200x200)的网址,则可以在网址中将200%3A200替换为800%3A600,以获取800x600的图片。您甚至可以使用1900%3A1200来获取1900x1200的图片

parseparse_post使用几乎相同的代码,因此可以在单独的函数中使用。

import scrapy
from scrapy.http import FormRequest

class MySpider(scrapy.Spider):

    name = 'myspider'

    def start_requests(self):
        urls = [
            #'https://www.zomato.com/new-york-city/waldys-wood-fired-pizza-penne-chelsea-manhattan/photos'
            'https://www.zomato.com/new-york-city/cafeteria-chelsea-manhattan/photos'
        ]

        for url in urls:
            #url = url + '?category=food'
            yield scrapy.Request(url=url, callback=self.parse)


    def parse(self, response):
        # small images 200x200
        #urls = response.xpath('//div[@id="thumbsContainer"]//img/@data-original').extract()
        #urls = response.xpath('//img[@class="res-photo-thumbnail thumb-load lazy-photo-inner"]/@data-original').extract()
        #yield {'image_urls': urls}

        # big images 800x600
        #urls = [url.replace('200%3A200', '800%3A600') for url in urls]
        #yield {'image_urls': urls}

        # big images 1900x1200
        #urls = [url.replace('200%3A200', '1900%3A1200') for url in urls]
        #yield {'image_urls': urls}

        data = {
            'res_id': '16761868', #, '16780723', # place ID
            'offset': '30',    # change it
            'category': 'all', # 'food'
            'action': 'fetch_photos',
            'index': '30',
            'limit': '10', # chage it
        }

        url = 'https://www.zomato.com/php/load_more_res_pics.php'
        yield FormRequest(url, callback=self.parse_post, formdata=data)

    def parse_post(self, response):

        urls = response.xpath('//img[@class="res-photo-thumbnail thumb-load lazy-photo-inner"]/@data-original').extract()
        urls = [url.replace('\/', '/') for url in urls]

        yield {'image_urls': urls}

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0',
    'ITEM_PIPELINES': {'scrapy.pipelines.images.ImagesPipeline': 1},
    'IMAGES_STORE': '.',
})

c.crawl(MySpider)
c.start()

我在Firefox的DevTools中发现了data

enter image description here