【爬虫自学笔记】---使用scrapy和普通爬虫爬取豆瓣电影Leon图片

之前按照别人的教程练习了一些爬取图片以及使用框架的实例,现在自己做图片的爬虫,内容为Leon Lai在豆瓣电影中的图片集,下载到本地保存,一共415张。

网页结构说明:

在图片集中可以轻松找到图片的链接地址,获取该地址保存即可。

网页每页显示30张图片,爬取415张图片,只需要在爬取一页完成后,修改start参数,每次加30重新进行请求即可。

一、使用scrapy框架

items.py,定义爬取的数据,存储图片的名称以及链接地址。

import scrapy


class LeonItem(scrapy.Item):
    img_name = scrapy.Field()
    img_url = scrapy.Field()

leon.py(spider)

注意:循环时,需要调用回调函数,重新对新的请求进行分析

# -*- coding: utf-8 -*-
import scrapy
from Leon.items import LeonItem
class LeonSpider(scrapy.Spider):
    name = 'leon'
    allowed_domains = ['movie.douban.com']
    offset = 0
    url = "https://movie.douban.com/celebrity/1036978/photos/?type=C&sortby=like&size=a&subtype=a&start="
    start_urls = [url+str(offset)]
    count = 1
    def parse(self, response):
        for each in response.xpath("//div[@class='cover']"):
            item = LeonItem()
            url = each.xpath("./a/img/@src").extract()[0]
            item['img_url'] = url
            item['img_name'] = 'p'+str(self.count)
            self.count += 1
            yield item
        if self.offset<390:
            self.offset += 30
        yield scrapy.Request(self.url + str(self.offset), callback=self.parse)

pipelines.py

注意:使用scrapy的Request定义的是一个请求对象,其不含content属性,无法下载图片,所以使用requests库来获取图片并进行存储。

# -*- coding: utf-8 -*-
import scrapy
import time
import requests
class LeonPipeline(object):
    def __init__(self):
        self.path  = r'D:\pic\images'
    def process_item(self, item, spider):
        print(item)
        im = requests.get(item['img_url'])
        fp = open(self.path + '\%s.jpg' % item['img_name'], 'wb')
        fp.write(im.content)
        fp.close()

setting.py

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134'
DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
}
ITEM_PIPELINES = {
   'Leon.pipelines.LeonPipeline': 300,
}

如果不设置user-agent则会产生403错误。

结果:

二、普通方法

from urllib.parse import urlencode
from requests.exceptions import RequestException
import time
import requests
from lxml import etree
#请求头文件
headers = {
   'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134'
}

def get_page_index(offset):
    #获取链接地址,使用字典的形式存储参数
    data = {
       'size': 'a',
       'sortby': 'like',
       'start': offset,
       'subtype': 'a',
       'type': 'C'
    }
    url = 'https://movie.douban.com/celebrity/1036978/photos/?'+urlencode(data)
    try:
        response = requests.get(url,headers=headers)
        #请求成功
        if response.status_code == 200:
            return response.text    #返回响应的内容
        return None
    except RequestException:
        print('请求索引页出错')
        return None
#解析index获取的响应内容,获取图片地址
def parse_page_index(html):
    html = etree.HTML(html)
    urls = html.xpath("//li/div[@class='cover']/a/img//@src")
    for url in urls:
        yield url
path = r'D:\pic\images'#r保持字符串的原始值,不进行转义
count = 1
def parse_page_detail(url):
    im = requests.get(url,headers=headers)
    global count
    fp = open(path+'\%s.jpg'% str(count),'wb')
    fp.write(im.content)
    fp.close()
    count += 1
def main(offset):
    html = get_page_index(offset)
    for url in parse_page_index(html):
        parse_page_detail(url)


if __name__ == '__main__':
    offset = 0
    #改变offset的值,进行多页爬取
    while offset<=390:
        main(offset)
        offset += 30

注意:因为感觉xpath比较好用,没有使用beautifulsoup,其实如果配合正则表达式的话也可以使用。

因为想统计图片的数量,并使用其对图片进行命名,计数变量必须是全局变量,但是又需要在函数中调用并改变数值,其方法是在函数中将其声明为全局变量。

猜你喜欢

转载自blog.csdn.net/m0_38103546/article/details/82056920