7

I have a web scraper that I want to download an image of the page it's scraping and save it as a "screenshot" ImageField in a Django model. I am using this code:

def save_screenshot(source,screenshot):
    box = (0, 0, 1200, 600)
    im = Image.open(io.BytesIO(screenshot))
    region = im.crop(box)
    tempfile_io = io.BytesIO()
    region.save(tempfile_io, 'JPEG', optimize=True, quality=70)
    source.screenshot.save(source.slug_name+"-screenshot",ContentFile(tempfile_io.getvalue()),save=True)

It saves the screenshot to the /media/news_source_screenshots/ directory but doesn't save it to the model. The model field is defined as:

screenshot = models.ImageField(upload_to='news_source_screenshots',blank=True,null=True)

What am I missing?

Anthony Ainsworth
  • 917
  • 1
  • 7
  • 9
  • I see that you're saving the tempfile without data, you must be save the `region`... in `source.screenshot.save(source.slug_name+"-screenshot", ContentFile(region.get_value()), save=True)`, remember that region os now your tempfile, cause tempfile_io is a void buffer – German Alzate Dec 30 '16 at 23:24
  • thanks @german-alzate-martinez but when I tried your fix I got: `code` TypeError: 'Image' does not support the buffer interface `code` and the image is not longer saved in the /media/news_source_screenshost/ directory – Anthony Ainsworth Dec 31 '16 at 00:40
  • Try change the buffer to string io, what return region? – German Alzate Dec 31 '16 at 00:41
  • I changed the line `tempfile_io = io.BytesIO()` to `tempfile_io = io.StringIO()` and got `TypeError: string argument expected, got 'bytes'` referring to the `region.save` line of code @german-alzate-martinez – Anthony Ainsworth Dec 31 '16 at 01:06
  • What return region with your original code? – German Alzate Dec 31 '16 at 01:22

1 Answers1

3

So it turns out the above code works great! The issue was that I was calling the above method using a piece of code like this:

source = NewsSource.objects.get(name=name)
html,screenshot = get_url(source.url)
save_screenshot(source,screenshot)
source.save()

So the save_sceenshot method worked but then the work it had done was overwritten by my source.save() call. Go figure!

Anthony Ainsworth
  • 917
  • 1
  • 7
  • 9