利用scrapy框架递归爬取菜谱网站

介绍:

最近学习完scrapy框架后,对整个运行过程有了进一步的了解熟悉。于是想着利用该框架对食谱网站上的美食图片进行抓取,并且分别按照各自的命名进行保存。

1、网页分析

爬取的网站是www.xinshipu.com,在爬取的过程中我发现使用xpath对网页进行解析时总是找不到对应的标签,但是xpath路径又没有错误。这点一直让我很费解,直到我手动将request获取到的响应源码保存到本地进行查看时才发现,请求到的网页跟浏览器端打开的网页结构完全不一样。后来通过查看图片的保存路径我发现网站上的图片都是保存在阿里的服务器上,因此猜想应该是阿里做的反爬虫的处理导致直接分析网页源码会失效吧,这点到底怎么实现的,因为现在还是小白,所以暂时还不清楚,留待以后解决吧。

如上图所示,为每道菜的网页源码,初步设想可以爬取a标签并用rel属性用作识别条件,然后将底下的img标签的src属性拿到。该属性是每道菜图片的存储地址。然后获得p标签中的文本内容。

对于每页的链接地址,网页源码如下:

 

这里可以获取a标签并且以rel属性用作识别条件,然后将识别出的a标签的href属性提取出来,然后将它和网站的域名结合起来,传递给调度器进行处理。

2、实现 

(1)实现数据的提取

首先定义数据对象结构,

import scrapy


class XinshipuItem(scrapy.Item):
    # define the fields for your item here like:
    name = scrapy.Field()
    img=scrapy.Field()
    pass

 如图所示,定义了图片的名字,以及图片的存储地址两个属性。

然后解析网页标签,如图所示,将每一个获得信息yield返回给pipline进行处理。

扫描二维码关注公众号,回复: 4636410 查看本文章
import scrapy
import requests
from xinshipu.items import XinshipuItem

class JiachangcaiSpider(scrapy.Spider):
    name = 'jiachangcai'
    allowed_domains = ['www.xinshipu.com']
    start_urls = ['https://www.xinshipu.com/jiachangzuofa/17844/']

    def parse(self, response):
        for each in response.xpath("//a[@rel='ImgClk']"):
            item= XinshipuItem()
            img=each.xpath("div/img/@src").extract()
            name=each.xpath("div/div/p/text()").extract()
            item['name']=name[0]
            item['img'] = img[0]
            yield item

接着对下一页的url进行提取,将提取的url组合后提交给调度器,通过回调函数调用parse进行解析。

suburl=response.xpath('//a[@rel="next"]/@href').extract()
        url_next="https://www.xinshipu.com%s"%suburl[0]
        print(url_next)
        yield scrapy.http.Request(url_next, callback=self.parse)

最后在pipline中对每一个item进行数据持久化操作,保存到本地并以对应的名字命名。

import requests
from requests import Session
class XinshipuPipeline(object):
    def process_item(self, item, spider):
        #print(item['img'])
        img=requests.get(url="https:%s"%item['img'])


        name=item['name']
        print(name)
        with open("%s.jpg"%name,"wb") as f:
            f.write(img.content)
            f.close()

        return item

3、结果

执行scrapy crawl jiachangcai 命令,得到爬取的结果:

总结补充

爬取过程中可以通过在setting中设置DEPTH_LIMT属性控制迭代网页的深度,但是我在设置后并没有起相关的作用,这里咱们不太清楚什么原因,留待以后解决吧!

猜你喜欢

转载自blog.csdn.net/ytz201201/article/details/84983197