scrapy高级操作

编辑本随笔

一、Scapy核心组件

  • 引擎:用来处理整个系统的数据流处理,出发事物
  • 管道:负责处理爬虫从网页上提取的实体信息,主要是持久化和验证实体的有效性,清楚不需要的信息。
  • 调度器:接受引擎发过来的请求,由它决定下一个要爬取的网址,去处重复网址
  • 下载器:下载网页内容,将网页发回给蜘蛛,scrapy
  • 爬虫文件:即蜘蛛,从特定的网页中提取自己需要的信息,即所谓的实体。用户也可以从中取出连接,让scrapy继续抓取下一个页面

二、Scapy的POST请求

POST发起方法,重写父类start_requests()方法:

  1. 将scrapy.Request()的method方法修改成post(不建议该方法),默认是get方法
  2. 使用scrapy.FormRequest()方法来发起POST请求(推荐该方法)

项目:post提交关键字到百度翻译

# -*- coding: utf-8 -*-
import scrapy

class PostdemoSpider(scrapy.Spider):
    name = 'postDemo'
    #allowed_domains = ['www.baidu.com']
    start_urls = ['https://fanyi.baidu.com/sug']

    #方法一、修改Request()方法,将method赋值成post,不推荐
    # def start_requests(self):
    #     for url in self.start_urls:
    #         yield scrapy.Request(url=url,callback=self.parse,method="post")

    #方法二、使用FormRequest方法,推荐
    def start_requests(self):
        data={
            "kw":"dog"
        }
        for url in self.start_urls:
            yield scrapy.FormRequest(url=url,formdata=data,callback=self.parse)
    def parse(self, response):
        print(response.text)
View Code

三、Scapy的cookie操作

不需要可以去添加cookie,会自动携带

# -*- coding: utf-8 -*-
import scrapy
class DoubandemoSpider(scrapy.Spider):
    name = 'doubanDemo'
    allowed_domains = ['www.douban.com']
    start_urls = ['https://accounts.douban.com/j/mobile/login/basic']

    #重写父类的start_requests方法,使其发送post请求
    def start_requests(self):
        #封装登陆信息
        data={
            "ck":"",
            "name":"用户名",
            "password":"密码",
            "remember":"false",
            "ticket":""
        }
        #通过FormRequest方法发送登陆请求
        for url in self.start_urls:
            yield scrapy.FormRequest(url=url,formdata=data,callback=self.parse)

    def parse(self, response):
        #登陆后先保存主页数据后请求获取个人主页数据
        fp=open("./index.html","w",encoding="utf-8")
        fp.write(response.text)
        fp.close()
        #个人主页url
        url="https://www.douban.com/people/191728538/"
        #这里会自动携带post请求之后的cookie参数
        yield scrapy.Request(url=url,callback=self.parseSecongPage)
    def parseSecongPage(self,response):
        #解析个人主页数据
        fp=open("./user_index.html","w",encoding="utf-8")
        fp.write(response.text)
        fp.close()
View Code

修改setting.py文件后执行爬虫

四、Scapy的proxy操作

免费代理地址点这里

下载中间件:拦截请求,可以将请求IP进行更换

流程:

下载中间件类的自定制,在middlewares.py文件中自定义Proxy类。重写process_request(self,request,spider)的方法

#自定义一个下载中间件类,在类中实现process_request()方法,处理中间件拦截到的请求
class MyProxy(object):
    def process_request(self,request,spider):
        #请求IP的更换
        request.meta["proxy"]="https://124.107.173.110:8080"

在配置文件中开启下载中间件,即DOWNLOADER_MIDDLEWARES

DOWNLOADER_MIDDLEWARES = {
   # 'proxyPro.middlewares.ProxyproDownloaderMiddleware': 543,
    'proxyPro.middlewares.MyProxy': 543,
}

通过代理请求一个查询ip的地址

五、Scapy日志等级

ERRPR:错误,错误代码必须修改

WARAING:警告,可修改可不修改,不影响代码执行

INFO:一般信息

DEBUG:调试信息(默认)

让终端输出指定级别的信息:

在setting.py文件中添加:

指定输出某级别日志信息:LOG_LEVEL="ERROR"

将日志存储到指定文件中:LOG_FILE="log.txt"

六、请求传参

爬取的数据值不在同一个页面当中。

需求:将id97.com电影网站中的数据进行爬取,包括(名称,类型,导演,语言,片长)等数据

知识点:使用scrapy.Request(url,callback,meta)方式传参给callback函数

meta必须是字典类型,在callback方法中用response.meta.get("key")即可获取传入的参数

spider页面:

# -*- coding: utf-8 -*-
import scrapy
from moviePro.items import MovieproItem

class MovieSpider(scrapy.Spider):
    name = 'movie'
    #allowed_domains = ['www.55xia.com']
    start_urls = ['https://www.55xia.com/movie']

    #解析二级页面内容
    def parseBySecondPage(self,response):
        actor=response.xpath("/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[1]/td[2]/a/text()").extract_first()
        language=response.xpath("/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[5]/td[2]/a/text()").extract_first()
        longtime=response.xpath("/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[8]/td[2]/text()").extract_first()

        #取出request方法的meta参数传递过来的字典
        item=response.meta.get("item")
        item["actor"] = actor
        item["language"] = language
        item["longtime"] = longtime

        #所有内容都存储到了item对象,将item对象提交给管道即可
        yield item

    def parse(self, response):
        #名称,类型,导演,语言,片长
        div_list=response.xpath("//div[@class='movie-item-in']")
        for div in div_list:
            name=div.xpath("./div[@class='meta']/h1/a/text()").extract_first()
            kind = div.xpath("./div[@class='meta']/div[@class='otherinfo']/a//text()").extract_first()
            url="https:"+div.xpath("./a/@href").extract_first()

            #创建items对象
            item=MovieproItem()
            item["name"]=name
            item["kind"] = kind
            #问题:二级页面数据怎么存入item类中。可使用meta传参给回掉函数,需字典类型

            #需要对url发起请求,获取页面数据,进行指定数据解析
            yield scrapy.Request(url=url,callback=self.parseBySecondPage,meta={"item":item})
View Code

我们穿给scrapy.Request()的url必须是带有协议头的完整url

pipelines管道页面:

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html


class MovieproPipeline(object):
    fp=None

    def open_spider(self,spider):
        self.fp=open("./movie.txt","w",encoding="utf-8")

    def process_item(self, item, spider):
        detail="%s:%s:%s:%s:%s\n" % (item['name'],item['kind'],item['actor'],item['language'],item['longtime'],)
        self.fp.write(detail)
        return item
    def close_spider(self,spider):
        self.fp.close()
View Code

item页面:

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class MovieproItem(scrapy.Item):
    name=scrapy.Field()
    kind=scrapy.Field()
    actor=scrapy.Field()
    language=scrapy.Field()
    longtime=scrapy.Field()
View Code

在setting文件中关闭robots协议,添加user-agent信息,并打开ITEM_PIPELINES

执行:scrapy crawl movie --nolog

会在项目文件夹下创建一个movie.txt文件

posted @ 2019-02-22 11:05  丫丫625202  阅读(572)  评论(0编辑  收藏  举报