爬虫--scrapy框架

爬虫(下) 

 

        --scrapy框架

一、基础学习 

1、scrapy框架示意图

2、scrapy框架安装和学习文档

安装:pip install scrapy
注: 
(1)在ubantu上安装scrapy之前,需要先安装一下依赖:
sudo apt-get install python -dev python-pip libxml12-dev libxslt1-dev zlibig-dev libffi-dev libss1-dev,然后在通过pip install scrapy安装
(2)在windows系统下,提示这个错误ModelNotFoundError:No module.... "win32api"
安装解决:pip install pywin32
(3)中文文档: http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html

3、使用步骤

(1)创建项目
使用命令:scrapy startproject 项目名称
项目结构说明
items.py:用来存放爬虫爬取下来数据的模型
middlewares.py:用来存放各种中间件的文件
pipelines.py:用来将items.py的模型存储到本地磁盘
settings.py:爬虫的一些配置信息(比如请求头、多久发送一次请求、ip代理等)
spiders包里面;存放所有的爬虫
scrapy.cfg:scrapy的项目配置文件

(2)创建一个爬虫
创建一个爬虫。并且能爬取的网页只会限制在www.qiushibaike.com这个域名下,www.部分可以不写
使用命令:scrapy genspider qsbk_spider "qiushibaike.com"
注意:先进入项目中spiders里面,在执行命令,保证爬虫的代码在spiders包里面
创建的爬虫文件说明
爬虫类必须继承scrapy.Spider类
类属性说明
name:表示爬虫的名字,有多个爬虫的话,名字必须唯一
allowed_domains:允许爬虫爬取域名的范围
start_urls:开始爬取的位置
类方法说明
parse():爬取到数据以后。自动执行parse,响应相关信息保存在response里面
response:是一个HttpResponse类型

(3)配置settings.py文件
推荐配置
ROBOTSTXT_OBEY = True:设置为False
DEFAULT_REQUEST_HEADERS:设置请求头,打开注释并添加:User-Agent请求头,伪装成浏览器
DOWNLOAD_DELAY:下载延迟时间1s,防止把服务器弄奔溃,DOWNLOAD_DELAY = 1

(4)items.py定义爬虫文件返回数据格式

class QsbkDownloadItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    dz_content = scrapy.Field()
    dz_jokes = scrapy.Field()
    dz_url = scrapy.Field()

(5)爬虫文件里面parse()方法里面处理数据

  • response对象属性和方法,<class 'scrapy.http.response.html.HtmlResponse'>,方法:xpath(),支持利用xpath获取数据。
  • 处理好以后以yield迭代器的方式给pipelines.py,yield数据items.py里面定义类的类型,也可以把每一项放在一个列表中一起return返回, 就不使用yield。
  • 爬取多个页面,使用scrapy.Request(url, callback)再次发起请求,url:发送请求的url页面,callbake:响应回来处理数据的函数,其实就是parse()函数
class QsbkDzSpiderSpider(scrapy.Spider):
    name = 'qsbk_dz_spider'
    allowed_domains = ['qiushibaike.com']
    start_urls = ['https://www.qiushibaike.com/text/page/1/']

    def parse(self, response):
        dz_contents = response.xpath("//*[@id='content']/div/div[2]/div")
        for dz in dz_contents:
            #段子内容
            dz_con = dz.xpath(".//div[@class='content']//span[1]/text()").getall()
            dz_content = "".join(dz_con).strip()
            # print(dz_content)
            #段子好笑数
            dz_jokes = dz.xpath(".//span[@class='stats-vote']/i/text()").get().strip()
            # print(dz_jokes)
            #完整段子url
            dz_url = dz.xpath(".//a[@class='contentHerf']/@href").get().strip()
            yield QsbkDownloadItem(dz_content =dz_content, dz_jokes=dz_jokes, dz_url=dz_url)

(6)pipelines.py存储数据

主要三个方法:
open_spider(self, spider):可使用__init__()方法代替,爬虫打开后自动调用,一般用于打开文件
process_item(self,item,spider):爬虫传递过来数据时自动调用(即执行了yield)
把数据传递给item参数,一般用于写入文件
close_spider(self, spider):爬虫关闭后自动调用,一般用于关闭文件

配置settings.py自动调用pipelines:打开注释ITEM_PIPLINES,字典里面,key代表pipline的位置,value:代表执行pipline优先级,值越小越高

用JsonItemExporter自动导出数据:

使用步骤:

导入JsonItemExporter类

from scrapy.exporters import JsonItemExporter

创建JsonItemExporter(fp, ensure_ascii=False,encoding="utf-8")对象

开始导出,JsonItemExporter对象的start_exporting()方法

导出数据,JsonItemExporter对象的export_item(item)方法

结束导出, sonItemExporter对象的finish_eexporting(),注:放在关闭文件前

这个类是每次把数据添加到内存中,最后统一写入磁盘。好处是存储的数据是一个满足json数据格式规则的数据。坏处是如果数据量过大,那么比较耗内存。

用JsonLinesExporter自动导出数据:
与使用方式sonItemExporter类似,但是不用写开始与结束
存储数据格式为,每个字典为一行,没有[]括起来
这个类是每次调用export_item,就把数据存储到硬盘中。坏处是每个字典是一行,整个文件不是满足json格式的文件,好处不耗内存,数据也比较安全

class QsbkDownloadPipeline:
    def __init__(self):
            self.fp = open("dz_joke.json", "wb")
            self.exp = JsonLinesItemExporter(self.fp, ensure_ascii=False, encoding="utf-8")
    def process_item(self, item, spider):
        self.exp.export_item(item)
        return item
    def close_spider(self, spider):
        self.fp.close()

(7)执行爬虫
方式一:直接终端输入命令
命令:scrapy crawl 爬虫名字
注:先进入虚拟环境,项目中,在执行命令
方式二:在python中使用命令,运行该.py文件
创建一个.py文件,名字任意
导入cmdline
from scrapy import cmdline
execute执行命令:cmdline.execute("scrapy crawl 爬虫名字".split())
等价于:cmdline.execute(["scrapy", "crawl", "爬虫名字"])

from scrapy import cmdline
cmdline.execute("scrapy crawl qsbk_dz_spider".split())

(8)总结

  1. 创建项目,创建一个爬虫
  2. 配置settings.py文件
  3. items.py定义爬虫文件返回数据格式
  4. 爬虫处理response后按照items.py定义的数据格式返回数据
  5. pipelines.py导出爬取的数据,用JsonItemExporter自动导出数据,用JsonLinesExporter自动导出数据

Scrapy Shell
我们想要在爬虫中使用xpath,beautifulsoup,正则表达式、css选择器等来提取想要的数据。但是因为scrapy是一个比较重的框架。每次运行起来都要等待一段时间。因此要去验证我们写的提取规则是否正确,是一个比较麻烦的事情。因此Scrapy提供了一个shell,用于方便测试。
打开终端进入到scrapy所在的目录,然后进入scrapy框架所在虚拟环境中
输入命令:scrapy  shell  url链接
就会进入到scrapy的shell环境中,就可以像在爬虫中使用parse()方法中一样使用 

二、CrawlSpider爬虫 

想要只要遇到满足某个条件的url,都给我进行爬取,那么就可以通过CrawlSpider实现,CrawlSpider继承自Spider,添加了新功能,可以自定义爬取的url规则,只要碰到满足条件的url自动进行爬取,不用手动yield Request。

LinkExtractors链接提取器:LinkExtractors类,自动提取满足规则的url,配合Rule规则类使用。

使用步骤:

1、创建CrawlSpider爬虫

scrapy genspider -t crawl 爬虫名字 域名

爬虫文件基本结构

2、配置start_urls-起始url,rules-需要爬取url的规则,注:scrapy框架会自动去除重复的url

3、在parse_xxxx(self, response)方法里面解析并返回数据给pipline

#xx_spider.py
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from qsbk_download.items import QsbkDownloadItem

class QsbkDzSpiderSpider(CrawlSpider):
    name = 'qsbk_dz_spider'
    allowed_domains = ['qiushibaike.com']
    #爬起数据起始页
    start_urls = ['https://www.qiushibaike.com/text/page/1/']
    #自动爬取url规则,callback指定处理该爬取该url规则的函数,follow是否在url规则返回数据里面跟踪满足条件的url

    rules = (
        Rule(LinkExtractor(allow=r'.+text/page/\d+'), callback='parse_page', follow=True),
#https://www.qiushibaike.com/article/124856819
        Rule(LinkExtractor(allow=r'.+article/\d+'), callback='parse_detail', follow=False),
    )

    def parse_page(self, response):
        # item = {}
        # #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
        # #item['name'] = response.xpath('//div[@id="name"]').get()
        # #item['description'] = response.xpath('//div[@id="description"]').get()
        # return item
        pass


    def parse_detail(self, response):
        """解析段子详情页"""
        #段子内容
        dz_content = "".join(response.xpath("//div[@class='content']/text()").getall()).strip()
        print(dz_content)
        #段子搞笑毒
        dz_funy = response.xpath("//i[@class='number']/text()").get().strip()
        print(dz_funy)
        #段子发布时间
        dz_datetime = response.xpath("//span[@class='stats-time']/text()").get().strip()
        print(dz_datetime)
        #段子url地址
        dz_url = response.url
        print(dz_url)
        #把数据传递给pipline
        yield QsbkDownloadItem(dz_content=dz_content, dz_funy=dz_funy, dz_datetime=dz_datetime, dz_url=dz_url)

4、pipline里面保存数据

#piplines.py
from itemadapter import ItemAdapter
from scrapy.exporters import JsonLinesItemExporter

class QsbkDownloadPipeline:
    def __init__(self):
            self.fp = open("dz_joke.json", "wb")
            self.exp = JsonLinesItemExporter(self.fp, ensure_ascii=False, encoding="utf-8")
    def process_item(self, item, spider):
        self.exp.export_item(item)
        return item
    def close_spider(self, spider):
        self.fp.close()

三、Request对象与Response对象 

Request对象:(from scrapy import Request
作用:爬取一页数据发送一个请求时调用。这个类需要传递一些参数。

常用参数
url: Request对象发送请求的url
callback: 在下载器下载完后处理数据的回调函数
method: 请求的方法,默认是GET方法,也可以设置成其他的
headers: 请求头,对于一些固定的设置,放在settings.py指定即可;对于非固定的,可以在发送请求时指定
meta: 比较常用,用于在不同请求之间传递数据用
encoding: 编码。默认utf-8,使用默认的就可以了
dot_filter: 默认True;设置为False表示不由调度器过滤,在执行多次重复的请求的时候用得比较多
errback: 发生错误的时候执行的函数

Response对象:
作用:Response一般是有scrapy框架自动帮我们构建的,可以用来提取数据

常用属性和方法
meta: 从其他请求传递过来的meta属性,可以保持多个请求之间的数据连接
encoding:返回当前字符串编码和解码的格式
text: 将返回来的数据作为unicode字符串返回(解码后的字符串,有时候可能解码不对,需要使用body进行手动解码)
body: 将返回来的数据作为bytes字符串返回
url:返回请求的url地址
xpath(): xpath选择器
css(): css选择器
urljoin(part_url):把不完整part_url根据域名自动合成完整url,返回值完整url 

四、发送POST请求

要发送POST请求,需要使用Request的子类FormRequest来实现。想要一开始就发送POST请求,需要在爬虫类中重写start_requests(self)方法,并且不再调用start_urls里面的url。

import scrapy


class TestPostSpiderSpider(scrapy.Spider):
    name = 'test_post_spider'
    allowed_domains = ['mail.qq.com']
    #重写start_requsets后,start_urls将不会生效
    start_urls = ['http://mail.qq.com/']

    def start_requests(self):
        url = "http://mail.qq.com/"
        data = {"email": "2361261017@qq.com", "password":"1059855897jyd"}
        request = scrapy.FormRequest(url, formdata=data, callback=self.parse_login)
        #这个请求不会登录成功,只是做个演示
        yield request
    def parse(self, response):
        pass
    def parse_login(self, response):
        #这里写登录成功后发送的请求
        pass

识别验证码:

(1)分析请求,构造formdata的时候携带验证码相关参数
(2) 三方验证码识别平台:https://market.aliyun.com/,搜索识别验证码

对图片进行base64编码与解码:使用内置模块base64

base64.b64encode(data):对图片二进制数据进行base64编码

base64.b64decode(data):对base64编码后的图片二进制数据进行解码

import base64
with open("123.jpg", "rb") as f:
    #对图片二进制数据进行base64编码
    base64_img = base64.b64encode(f.read())
print(base64_img)
with open("123副本.jpg", "wb") as f:
    #对base64编码后的图片二进制数据进行解码
    b_img = base64.b64decode(base64_img)
    f.write(b_img)

五、下载文件和图片

Scrapy为下载item中包含的文件(比如爬取到某个产品时,同时也想保存响应的图片)提供了一个可重用的item piplines。
这些pipline有些共同的方法和结构(称为media pipeline)。一般使用Files Pipline 或者 Images Piplines

选择scrapy内置下载文件方法的好处:

  1. 避免重新下载最近已经下载过的数据
  2. 可以方便的指定文件存储路径
  3. 可以将下载的图片转换成通用的格式。比如png或jpg
  4. 可以方便生成缩略图
  5. 可以方便检测图片的宽和高,确保他们满足最小限制
  6. 异步下载效率非常高

下载文件的FilesPipeline使用步骤:

1、定义好一个Item,然后在这个item中定义两个属性,分别为file_urls以及files。file_urls是用来存储需要下载的图片的url连接,需要给一个列表

2、当文件下载完成后,会把文件下载的相关信息存储到item的files属性中。比如下载路径,下载的url和文件的校验码等

3、在配置文件settings.py中配置FILES_STORE,这个配置是用来设置图片下载路径的

4、启动pipeline:在settings.py中配置ITEM_PIPLINES设置scrapy.pipelines.files.FilesPipeline:1

下载图片的ImagesPipline使用步骤:

1、定义好一个Item,然后在这个item中定义两个属性,分别为image_urls以及images。image_urls是用来存储需要下载的图片的url连接,需要给一个列表

2、当文件下载完成后,会把文件下载相关信息存储到item的images属性中。比如下载路径,下载的url和图片的校验码等

3、在配置文件settings.py中配置IMAGES_STORE,这个配置是用来设置图片下载路径的

4、启动pipeline:在settings.py中配置ITEM_PIPLINES设置scrapy.pipelines.images.ImagesPipeline:1

重写ImagesPipline:

为了对文件进行分类,就需要重写这个类(自定义一个类继承自scrapy.pipelines.images.ImagesPipeline)

1、重写get_media_requests(self, item, info)方法:这个方法是发送请求之前调用,其作用就是发送下载请求

2、重写file_path(self, request, response=None,info=None)方法:这个方法是在图片将要被存储的时候调用,其作用是获取这个图片存储的路径

3、启动pipeline:在settings.py中配置ITEM_PIPLINES设置自己重写的pipeline 

#xx_spider.py
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from qsbk_download.items import QsbkDownloadImageItem

class QsbkImgSpiderSpider(CrawlSpider):
    name = 'qsbk_img_spider'
    allowed_domains = ['qiushibaike.com']
    start_urls = ['https://www.qiushibaike.com/imgrank/page/1/']

    rules = (
        #https://www.qiushibaike.com/imgrank/page/2/
        Rule(LinkExtractor(allow=r'.*/imgrank/page/\d+'), callback='parse_item', follow=True),
        #https: // www.qiushibaike.com / article / 124999370
        Rule(LinkExtractor(allow=r'.*/article/\d+'), callback='parse_detail', follow=False),
    )

    def parse_item(self, response):
        # item = {}
        #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
        #item['name'] = response.xpath('//div[@id="name"]').get()
        #item['description'] = response.xpath('//div[@id="description"]').get()
        # return item
        pass
    def parse_detail(self, response):
        content = response.xpath("//div[@class='image']/div[@class='content']/text()").get().strip()
        # print(content)
        img_url = response.urljoin(response.xpath("//div[@class='image']/div[@class='thumb']/img/@src").get().strip())
        # print(img_url)
        item = QsbkDownloadImageItem(image_urls=[img_url, ], images=content)
        yield item
#pipelines.py
from scrapy.exporters import JsonLinesItemExporter
from scrapy.pipelines.images import ImagesPipeline
import time
.
.
.
class QsbkDownloadImagePipeline(ImagesPipeline):
    """自定义下载图片piplines"""
    def file_path(self, request, response=None, info=None, *, item=None):
        download_time = "%s年%s月%s日" % tuple(time.strftime("%Y-%m-%d", time.localtime()).split("-"))
        img = request.url.split("/")[-1]
        img_name = img.split(".")[0]
        print(item)
        return '%s/%s.jpg' % (download_time, img_name)
#settings.py
ITEM_PIPELINES = {
   # 'qsbk_download.pipelines.QsbkDownloadPipeline': 300,
   # 'scrapy.pipelines.images.ImagesPipeline': 200,
    'qsbk_download.pipelines.QsbkDownloadImagePipeline':10,
}
IMAGES_STORE = ".//dz_img"

六、下载器中间件

下载器中间件是引擎和下载器之间通信的中间件。在这个中间件中我们可以设置代理、更换请求头等来达到反反爬虫的目的。要写下载器中间件,可以在下载器中实现两个方法:
1、process_request(self, request, spider):这个方法会在请求发送之前执行

process_request(self, request, spider)

作用:下载器发送请求前执行,一般可以在这里设置随机代理IP,随机请求头

参数:request --发送请求的request对象; spider --发送请求的spider对象

返回值:

如果返回None:Scrapy将继续处理该请求,执行其他中间件中相应方法,直到合适的下载器处理函数被调用

返回Response对象:Scrapy将不会调用任何其他的process_request()方法,将直接返回这个response对象。已经激活的中间件的process_response()方法则会在每个response返回时被调用

返回Request对象:不在使用之前的request对象去下载数据,而是根据现在返回的request对象返回数据

如果该方法中出现了异常,则对调用process_exception方法

2、process_response(self,request,response,spider):这个方法是数据下载到引擎之前执行

 process_response(self,request,response,spider)

作用:这个方法是下载器下载的数据到引擎之前会执行的方法

参数:request --request对象;response --被处理的response对象;spider --spider对象

返回值:

返回Response对象:会将这个新的response对象传给其他中间件,最终传给爬虫

返回Request对象:下载器链被切断,返回的request会重新被下载器调度下载

如果抛出一个异常,那么调用request的errback方法,如果没有指定这个方法,那么会抛出一个异常

3、使用步骤:

(1)创建一个类,写在middlewares.py中:

(2)实现相关需要的中间件方法,如:

        process_request(self, request, spider)

        process_response(self,request,response,spider)

(3)在settings.py中打开DOWNLOADER_MIDDLEWARES并把写好的中间件类配置在里面

 4、随机请求头中间件

爬虫频繁访问一个页面的时候,如果请求头保持一致。那么很容易被服务器发现,从而禁掉这个请求头。
注:重复访问一个网址
Scrapy有自动去重的功能,如果不想去重,把发送请求Requset对象的dont_filter设置为True。【scrapy.Request(url, dont_filter=True)】

#在middlewares.py里面写,并在setting.py里面注册中间件类后生效

class TestMiddleware:
    """自定义中间件"""
    USER_AGENT = [
    "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
    "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
    "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
    "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
    "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
]
    def process_request(self, request, spider):
        user_agent = random.choice(self.USER_AGENT)
        print("在my_process_reusets---设置请求头:", user_agent)
        request.headers["User_Agent"] = user_agent

5、IP代理池中间件 

#在middlewares.py里面写,并在setting.py里面注册中间件类后生效

class TestMiddleware:
    """自定义中间件"""
    USER_AGENT = [
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
    "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
    "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
    "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
    "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
]
    PROXIES = ["14.215.212.37:9168", "","27.208.139.89:8060"]
    def process_request(self, request, spider):
        #设置随机请求头
        user_agent = random.choice(self.USER_AGENT)
        request.headers["User_Agent"] = user_agent
        print("在my_process_reusets---设置请求头:", user_agent)
        #设置随机代理
        proxy = random.choice(self.PROXIES)
        request.meta['proxy'] = proxy
        print("在my_process_reusets---设置代理:", proxy)

七、使用twisted异步存储到MySQL数据库中

需要安装pymysql模块
twisted是安装scrapy自带的
在pipelines.py中存储数据,创建一个pipline类存储数据

使用步骤:        

1、twisted中导入adbapi
        
from twisted.enterprise import adbapi

2、使用adbapi创建一个连接池

        dbprames = {

                 'host':'127.0.0.1',

                 'port':3306,

                 'user':'root',

                 'password':'fy001',

                 'database':'test01', 

                 'charset':'utf8',

                 'cursorclass':cursor.DictCursor,                

        }

        dppool = adbapi.ConnectionPool('pymysql', **dbparames)
注:cursors.DictCursor是pymysql模块里面的游标对象,用于插入数据

3、使用连接池dbpool对象的runInteraction(func)执行插入数据的函数
        
runInteraction()方法会返回一个defer对象,用于处理添加数据时候的错误的函数
        defer.addErrback(func, *args)

class QsbkDownloadToMysqlPipeline:
    """存储到mysql数据库的Pipeline"""

    def __init__(self):
        self.dbprames = {"host": "127.0.0.1", "port": 3306, "user": "root", "password": "123456", \
                         "database": "qsbk", "charset": "utf8", "cursorclass": pymysql.cursors.DictCursor}
        self._sql = "insert into qsbk_dz values(%s,%s,%s)"  # url, content, funy
        self.dbpool = adbapi.ConnectionPool("pymysql", **self.dbprames)

    def process_item(self, item, spider):
        refer = self.dbpool.runInteraction(self.inset_item, item)
        refer.addErrback(self.inset_error, item, spider)

    def inset_item(self, cursor, item):
        cursor.execute(self._sql, (item["dz_url"], item["dz_content"], item["dz_funy"]))

    def inset_error(self, error, item, spider):
        print("出现错误".center(100, "-"))
        print(error)

八、 scrapy嵌入selenium + chromdriver

使用中间件,让chromdriver处理请求,返回chormdriver生成的页面

使用步骤:

1、创建一个中间件类,构造一个driver对象

        self.driver = webdriver.Chorme(executable_path="chromdriver路径")

2、在process_request(self, request,spider)方法中利用dirver处理请求,并用driver获取到的页面构造一个响应并返回

        self.driver.get(request.url)

        time.sleep(1) #等待页面数据生成

        source = self.driver.page_source

        response = HtmlResponse(url=self.current_url, body=source, request=request)

        return reponse

九、分布式爬虫 

scrapy-redis组件,利用redis分布式功能集成到scrapy框架中

编写Scrapy-Redis分布式爬虫
将一个Scrapy项目变成一个Scrapy-redis项目只需修改以下三点:
1、将爬虫的类从scrapy.Spider修改成scrapy_redis.spiders.RedisSpider
或从scrapy.CrawlSpider变成scrapy_redis.spiders.RedisCrawlSpider
2、将爬虫的start_urls删掉。增加一个redis_key = "xxx"。 这个redis_key是为了以后在redis中控制爬虫启动的。爬虫的第一个url,就是在redis中通过这个发出去的
3、在配置文件中增加配置
#Scrapy-Redis相关配置
#确保request存储到redis中
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#确保所有爬虫共享相同的去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFileter"
#设置redis为item pipline
ITEM_PIPLINES = {"scrapy_redis.pipelines.RedisPipline":300}
#在redis中保持scrapy-redis用到的队列,不会清理redis中的队列,从而可以实现暂停恢复功能
SCHEDULER_PERSIST =True
#设置连接redis信息
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
4、运行爬虫
在爬虫服务器上,进入爬虫文件所在路径,然后输入命令:scrapy runspider 爬虫名字在redis服务器上,推入一个开始的url链接:(注:redis_key和爬虫文件里面redis_key要一致)
redis-cli  
lpush redis_key start_url

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值