Python-Scrapy爬取妹子图

↘锁芯ラ 提交于 2021-02-15 12:25:19

写在开始:

学习网址>>>>
https://segmentfault.com/a/1190000003870052
scrapy.ItemLoad>>>http://docs.pythontab.com/scrapy/scrapy0.24/topics/loaders.html
流程>>>http://www.jianshu.com/p/5b6fbf9245f8
翻页>>>http://blog.sina.com.cn/s/blog_737463190102wk8x.html
Log>>>http://blog.csdn.net/arbel/article/details/7781121

一些注意点>>>>
网站:
    网站每页有多个meizi主题,每页页码格式:http://www.meizitu.com/a/list_1_1.html
        进入某个meizi内容页面,页码格式:http://www.meizitu.com/a/5460.html
            每个页面包括多张图片,具体图片地址:http://mm.howkuai.com/wp-content/uploads/2016a/09/02/01.jpg
网站列表页格式有更改,len(pages)会进入无限循环
网站增加了检查,需增加headers

item:
    使用ItemLoader来进行数据归集


spider:
    yield有迭代功能,代替循环
    首页,爬虫入口,中部是图片链接,下部有分页信息
    列表页,由分页信息进来,爬虫获得后续的url,每个列表页下部有分页
    内容页,由首页和列表页url过来处理,获得下载图片的url
    流程:
        开始页:start_urls=('http://www.meizitu.com/a/list_1_1.html',)
        获取当前列表页中内容页链接:for link in sel.xpath(''//li[@class="wp-item"]/div/h3/a/@href').extract()>>>
            处理第一个内容页:[callback=self.parse_item]>>>
                获取内容页中图片链接:l.add_xpath('image_urls', "//div[@id='picture']/p/img/@src", Identity())>>>
                    循环处理内容页中图片[pipeline]
            转入下一内容页[yield request]
                ......

        文件页列表集合:pages=sel.xpath('//*[@id="wp_page_numbers"]/ul/li/a/@href').extract()
        下一页地址: page_link=pages[-2]
        转入下一列表页[yield request]>>>
            转入第一个内容页>>>获取内容页中图片链接>>>循环处理内容页中图片
            转入下一内容页>>>获取内容页中图片链接>>>循环处理内容页中图片

pipeline:
    需要增加header

logging:
    没有成功,后续再完善

1.需建创建scrapy的project,可以新建一个CreateProj.py的文件;并且在参数中输入新建项目的名称

# -*- coding: utf-8 -*-
from scrapy import cmdline
#创建一个Project,需要在parameter中填定startproject YOUR_PROJECT_NAME
cmdline.execute()  

2.定义ITEM,一般建立在items.py

import scrapy

#定义Item类,用以存储spider获取的所需要数据
class MeizituItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    url = scrapy.Field()            #处理页面地址
    name = scrapy.Field()           #文件名
    tags = scrapy.Field()           #标签
    image_urls = scrapy.Field()     #图片网络链接地址
    images = scrapy.Field()         #图片本地存储地址

3.创建spider,这里有两个不同的spider

A.MeiziSpider,用的是循环列表页地址来进行处理

# -*- coding: utf-8 -*-
import scrapy
#Selector refer http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/selectors.html
from scrapy.selector import Selector
#Item Loader provide an easy way to catch:Items
from scrapy.contrib.loader import ItemLoader,Identity
from meizitu.items import MeizituItem

class MeiziSpider(scrapy.Spider):
    name="meizitu"
    allowed_domains=["meizitu.com"]     #No need http://
    start_urls=('http://www.meizitu.com/a/list_1_1.html',)   #start webpage

    def parse(self,response):
        print "开始爬虫>>>>>>>>>>>>>>>>>>>>>>>>>>>"
        #sel是页面源代码,载入scrapy.selector转成xpath/CSS
        sel=Selector(response)
        #连接用@href属性,获取图片链接
        for link in sel.xpath('//li[@class="wp-item"]/div/h3/a/@href').extract():
            #请求=Request(连接,parse_item),用以处理当前页面信息
            print "当前列表页中内容页链接->>>"+str(link)
            request=scrapy.Request(link,callback=self.parse_item)
            yield request       #返回至请求
        #获取页码集合
        pages=sel.xpath('//*[@id="wp_page_numbers"]/ul/li/a/@href').extract()
        #获取当前页
        # page = sel.xpath('//*[@id="wp_page_numbers"]/ul/li[@class="thisclass"]')
        # page=page[0].text
        print 'pages: %s'%pages,type(pages)   #打印当前页码
        if len(pages)>9:   #当#如果页码集合>某一值
            page_link=pages[-2]  #下一页=读取页码集合的倒数每二个页码
            page_link=page_link.replace('/a/','')   #图片连接=page_link(a替换为空)
            request=scrapy.Request('http://www.meizitu.com/a/%s' % page_link,
                                   callback=self.parse)    #处理下一页
            print "下一页是->>>" + str(page_link)
            yield request  #返回请求

    def parse_item(self,response):
        #l=用ItemLoader载入MeizituItem()
        print "处理内容页存入ITEM-->>>"+str(response)
        l=ItemLoader(item=MeizituItem(),response=response)
        #name
        l.add_xpath('name','//h2/a/text()')
        #tags
        l.add_xpath('tags', "//div[@id='maincontent']/div[@class='postmeta  clearfix']/div[@class='metaRight']/p/text()")
        #picture link
        l.add_xpath('image_urls', "//div[@id='picture']/p/img/@src", Identity())
        #url
        l.add_value('url',response.url)
        return l.load_item()

B.mzt_Spider运用rules来进行迭代匹配列表,有个缺点是旁边的页码也会进行循环

# -*- coding: utf-8 -*-
#another spider for meizitu which use LinkExtractor

from scrapy.selector import Selector                    #引入Selector分析xpath
from scrapy.contrib.spiders import CrawlSpider,Rule     #引入爬虫
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.contrib.loader import ItemLoader,Identity
from meizitu.items import MeizituItem                   #引入item类

class mzt_Spider(CrawlSpider):   #定义spider
    name="mzt"                      #定义spider名称
    allowed_domains=["meizitu.com"]    #定义spider限制区域
    start_urls=["http://www.meizitu.com/a/list_1_1.html"]   #spider开始


    rules=[
        #CrawlSpider匹配列表页规则,用以翻页
        #follow = True表示会在返回的url中继续寻找符合条件的url,\d+
        Rule(SgmlLinkExtractor(allow=(r'http://www.meizitu.com/a/list_1_\d\.html')),
                follow=True),
        #CrawlSpider匹配下一层规则
        Rule(SgmlLinkExtractor(allow=(r'http://www.meizitu.com/a/\d+\.html')),
             #使用函数进行处理
             callback="parse_item"),
    ]

    def parse_item(self,response):
        #l=用ItemLoader载入MeizituItem()
        print "处理内容页存入ITEM-->>>"+str(response)
        l=ItemLoader(item=MeizituItem(),response=response)
        #name
        l.add_xpath('name','//h2/a/text()')
        #tags
        l.add_xpath('tags', "//div[@id='maincontent']/div[@class='postmeta  clearfix']/div[@class='metaRight']/p")
        #picture link
        l.add_xpath('image_urls', "//div[@id='picture']/p/img/@src", Identity())
        #url
        l.add_value('url',response.url)
        return l.load_item()

4.建立pipeline,一般作为数据存储,这里添加了将ITEM写入txt功能。

import requests
from meizitu import settings
import os
#网站增加验证,需增加headers
head= {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) '
                  'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36'}

class ImageDownloadPipeline(object):
    def process_item(self, item, spider):
        print "开始pipeline-->"
        if 'image_urls' in item:  #如果'图片地址'在项目中
            print "开始图片保存-->"
            images=[]
            #自定义存储目录
            dir_path='%s\\%s' %(settings.IMAGES_STORE,spider.name)
            # print dir_path
            if not os.path.exists(dir_path):        #判别地址是否存在
                os.makedirs(dir_path)               #建创文件夹
            #循环图片地址
            for image_url in item['image_urls']:
                chunkSize=1024                      #单次请求最大值
                us=image_url.split('/')[3:]         #文件地址按/分割
                image_file_name='_'.join(us)        #命名为文件名
                file_path='%s\\%s'%(dir_path,image_file_name)    #文件地址
                images.append(file_path)
                if os.path.exists(file_path):
                    continue

                with open(file_path,'wb') as handle:                 #获取文件夹权限
                    response=requests.get(image_url,headers=head,stream=True)    #need to set steam=True parameter
                    for chunk in response.iter_content(chunk_size=chunkSize):
                        if chunk:
                            handle.write(chunk)                 #保存图片

                    handle.close()

            item['images']=images       #images信息存入ITEM[images]

            print "开始保存TXT>>>>>>"
            f=open("mzt.txt",'a+')
            for key in item:                            #循环item,格式为dict
                f.write(key)
                f.write(":")
                for i in item[key]:                     #循环item内容,格式为list
                    i=i.encode('utf-8')                 #需要转码
                    i=str(i).replace("\r\n","")
                    f.write(i)
                    f.write("\n")
            f.close()
        return item

5.进行settings.py的设置

BOT_NAME = 'meizitu'      #->MeiziSpider
# BOT_NAME = 'mzt'        #->mzt_Spider

SPIDER_MODULES = ['meizitu.spiders']
NEWSPIDER_MODULE = 'meizitu.spiders'
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.5 ' \
             '(KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
DOWNLOAD_DELAY = 0.25
ITEM_PIPELINES = {
    'meizitu.pipelines.ImageDownloadPipeline': 1}
#存储地址
IMAGES_STORE="C:\\Users\\zhengt\\Desktop\\mzt"      #存储地址

 

6.创建一个run_meizitu.py进行运行spider

# -*- coding: utf-8 -*-
# 新建一个运行爬虫的模块
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from meizitu.spiders.MeiziSpider import MeiziSpider   #引入spider类
from meizitu.spiders.mzt_Spider import mzt_Spider   #引入spider类

# 获取setting.py模块设置
settings = get_project_settings()  # 设置
process = CrawlerProcess(settings=settings)

# 添加spider,可以添加多个spider
process.crawl(MeiziSpider)
# process.crawl(mzt_Spider)
# 启动spider
process.start()

结果,运行了5分钟,下了10M,68个项目。

后续:logging没有成功.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!