使用セレンScrapyフレームキャプチャダイナミックケース] --2019-08-07 12時52分17秒

オリジナル:http://106.13.73.98/__/143/

導入


       いくつかのサイトをクロールデータScrapyフレームワーク、多くの場合、動的な負荷データ・ページを使用している場合。それが直接使用されている場合はScrapyのURLが要求を開始し、それが絶対的にデータを動的にロードされますされていません。しかし、我々は観察しています、対応する動的データをロードするブラウザを使用してそのURLへの要求を開始しました。我々は、動的Scrapyにロードされたデータを取得したいのであれば、あなたが使用する必要があり、セレンのブラウザを動作させるために、その後、動的にロードされたデータを取得するためにブラウザからそのURLへの要求を開始します。

ケーススタディ


  • 需要の国内、国際、軍用、航空部門の網易のニュースの下でクロールニュースデータ:

  • 要件分析:あなたはページの板部にハイパーリンクをクリックすると、データのうちニュース動的にロードさを示すために、現在のページを見つけます。したがって、我々は、使用する必要がセレンを動的にロードされたデータを取得するために彼らのブラウザを動作させます。

プロセスにおけるセレンのScrapy使用:


  1. コンストラクタオーバーライド爬虫類は、使用方法でセレンブラウザ・オブジェクトの例(ブラウザなどのオブジェクトを一度だけインスタンス化されます)。
  2. 書き換え爬虫類ファイルは閉じられ、内部近いブラウザオブジェクトで、メソッドを。この方法は、爬虫類の終了時に呼び出されます。
  3. リライトダウンロード(またはクローラ)ミドルウェアprocess_responseを傍受する応答オブジェクトのメソッドとタンパーための方法応答のページデータが格納されています。
  4. 設定ファイルでダウンロードしたミドルウェアを開きます。

コード表示


爬虫類のファイル:

# -*- coding: utf-8 -*-
import scrapy
from selenium import webdriver
from aip import AipNlp  # pip install baidu-aip
from Test.items import TestItem


class TestSpider(scrapy.Spider):
    name = 'test'
    start_urls = ['https://news.163.com/']  # 网易首页

    # 用于存放四大板块详情页的超链接,在下载中间件中会用到
    plate_page = []

    # 百度AI,用于提取文章关键字和类型,详见文档:https://ai.baidu.com/docs#/NLP-Python-SDK/cf2f8fbe
    __APP_ID = '15225447'
    __API_KEY = 's5m43BMMEGGPaFGxeX3SsY7m'
    __SECRET_KEY = 'Lca9FEGpWNZW6yd8WWAHAyCyLovmi6rb'
    client = AipNlp(__APP_ID, __API_KEY, __SECRET_KEY)


    def __init__(self):
        # 实例化一个谷歌浏览器对象,在下载中间件中会用到
        self.bro = webdriver.Chrome(executable_path=r'V:\Folder\software\谷歌浏览器V69-71版本的驱动\chromedriver.exe')
        # executable_path:指定你的谷歌浏览器驱动


    # 重写父类方法,用于关闭浏览器
    def closed(self, spider):
        """此方法在爬虫程序结束时执行,注意:只会执行一次"""
        self.bro.quit()
        print('爬取结束')


    def parse(self, response):
        # 获取所有板块的链接
        all_li_list = response.xpath('//div[@class="ns_area list"]/ul/li')
        # 提取指定板块的链接(3-国内,4-国际,6-军事,7-航空)
        sign_li_list = [all_li_list[i] for i in [3, 4, 6, 7]]

        # 下面将对提取的四大板块进行解析,并访问其页面
        for li in sign_li_list:
            url = li.xpath('./a/@href').extract_first()
            self.plate_page.append(url)
            # 访问每个版块页面
            yield scrapy.Request(url, callback=self.parse_plate_page)
            # callback:指定回调函数,即解析的方法


    # 用于解析四大板块页面
    def parse_plate_page(self, response):
        # 注意,此页面中的数据是动态加载的,在下载中间件中来获取动态数据
        div_list = response.xpath('//div[@class="ndi_main"]/div')  # 获取所有文章对应的<div>

        # 提取文章基本信息
        for div in div_list:
            if not div.xpath('./a/img/@alt'): continue  # 过滤其它标签格式的文章
            item = TestItem()
            item['title'] = div.xpath('./a/img/@alt').extract_first()  # 文章标题
            item['img_url'] = div.xpath('./a/img/@src').extract_first()  # 文章标题图片对应的链接
            detail_url = div.xpath('./a/@href').extract_first()  # 文章详情页的url
            # 访问每篇文章的详情页面
            yield scrapy.Request(detail_url, callback=self.parse_detail_page, meta={'item': item})
            # meta={'item': item}:将当前的item对象传入解析方法


    # 用于解析所有文章的详情页面
    def parse_detail_page(self, response):
        # 我们先提取出传过来的参数
        item = response.meta['item']

        # 获取文章的所有内容并全部解析后保存
        content = response.xpath('//div[@id="endText"]//text()').extract()
        item['content'] = ''.join(content).strip(' \n\t')

        # 下面将调用百度AI接口,提取文章的关键字和类型:
        # 实测中有编码问题,这里我们将其替换为空来解决
        args = {'title': item['title'].replace(u'\xa0',u''), 'content': item['content'].replace(u'\xa0',u'')}
        # 开始提取文章关键字
        keys = self.client.keyword(**args)
        item['keys'] = ' '.join([dct.get('tag') for dct in keys.get('items')])  # 保存文章关键字
        # 开始提取文章类型
        kinds = self.client.topic(**args)
        item['kind'] = kinds.get('item')['lv1_tag_list'][0]['tag']  # 保存文章类型

        # 将准备好的item对象提交给管道,剩下的就是保存数据了
        yield item 

データ構造テンプレートファイル:
python import scrapy class TestItem(scrapy.Item): # define the fields for your item here like: title = scrapy.Field() # 文章标题 img_url = scrapy.Field() # 文章标题图片对应的链接 content = scrapy.Field() # 文章内容 keys = scrapy.Field() # 文章关键字 kind = scrapy.Field() # 文章类型

ミドルウェアのファイル:

from time import sleep from
from scrapy.http import HtmlResponse  # 用于生成响应对象


# 下载中间件 class TestDownloaderMiddleware(object):

    def process_response(self, request, response, spider):
        """
        此方法用于拦截响应
        :param request: 当前响应对应的请求
        :param response: 响应
        :param spider: 爬虫类对象
        :return:
        """

        # 我要要在这里拦截四大板块页面的响应,来获取动态加载的内容

        # 对于不是访问四大板块页面的,直接放行:
        if request.url not in spider.plate_page:
            return response


        # 能走到这里的,必然是四大板块的响应,下面将篡改响应对象

        # 获取在爬虫类中创建好的浏览器对象
        bro = spider.bro
        # 向板块页面发起GET请求
        bro.get(url=request.url)
        sleep(1)

        # 鼠标滚轮下滚,连滚两次(用于获取更多动态加载的数据)
        js = 'window.scrollTo(0, document.body.scrollHeight);'
        bro.execute_script(js)
        sleep(0.5)
        bro.execute_script(js)
        sleep(0.5)

        # 获取页面源码,这里有我们需要的动态加载的数据
        page_text = bro.page_source
        # 创建一个新的响应对象,并将动态加载到的数据存入该对象中,然后返回该对象
        return HtmlResponse(url=bro.current_url, body=page_text, encoding='utf-8', request=request)
        # bro.current_url:请求的url 

パイプファイル:

"""去吧,创建你的数据表:
create table test01(
  id int primary key auto_increment,  -- 自增id
  title varchar(128),  -- 标题
  img_url varchar(128),  -- 标题图片对应的链接
  keyword varchar(64),  -- 关键字
  kind varchar(32),  -- 文章类型
  content text  -- 文章内容
);
"""

import pymysql


class TestPipeline(object):

    # 重写父类方法,用于建立MySQL链接,并创建一个游标
    def open_spider(self, spider):
        """此方法在运行应用时被执行,注意:只会被执行一次"""
        self.conn = pymysql.Connect(
            host='localhost',
            port=3306,
            user='zyk',
            password='user@zyk',
            db='test',  # 指定你要使用的数据库
            charset='utf8'  # 指定数据的编码格式
        )  # 建立MySQL链接

        # 创建游标
        self.cursor = self.conn.cursor()


    def process_item(self, item, spider):
        # 我们先准备好sql语句
        sql = 'insert into test01(title, img_url, keyword, kind, content) values(%s, %s, %s, %s, %s)'

        # 开始执行事务
        try:
            self.cursor.execute(sql, (item['title'], item['img_url'], item['keys'], item['kind'], item['content']))  # 写入数据
            self.conn.commit()  # 提交
            print(item['title'], '已保存')
        except Exception as e:
            self.conn.rollback()  # 回滚
            print(e)

        return item


    # 重写父类方法,用于关闭MySQL链接
    def close_spider(self, spider):
        """此方法在结束应用时被执行,注意:只会被执行一次"""
        self.cursor.close()  # 关闭游标
        self.conn.close()  # 关闭连接 

プロファイル:

# 伪装请求身份载体(User-Agent) 
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87
Safari/537.36'

# 是否遵守robots协议 
ROBOTSTXT_OBEY = False

# 开启的线程数 
CONCURRENT_REQUESTS = 100

# 禁用cookie来提升爬取效率 
COOKIES_ENABLED = False

# 提高日志级别来降低CPU的占用率,以提升爬取效率 
LOG_LEVEL = 'ERROR'

# 禁用重新请求(对失败的rul)来提升爬取效率 
RETRY_ENABLED = False

# 开启管道 
ITEM_PIPELINES = {
    'Test.pipelines.TestPipeline': 300, 
}

# 启用下载中间件 
DOWNLOADER_MIDDLEWARES = {
    'Test.middlewares.TestDownloaderMiddleware': 543, 
} 

オリジナル:http://106.13.73.98/__/143/

おすすめ

転載: www.cnblogs.com/gqy02/p/11314641.html