最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Scrapy框架介紹之Puppeteer渲染的使用

 更新時間:2020年06月19日 10:36:15   作者:Laicaling  
這篇文章主要介紹了Scrapy框架介紹之Puppeteer渲染的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1、Scrapy框架

Scrapy是用純Python實現(xiàn)一個為了爬取網(wǎng)站數(shù)據(jù)、提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架,用途非常廣泛。
框架的力量,用戶只需要定制開發(fā)幾個模塊就可以輕松的實現(xiàn)一個爬蟲,用來抓取網(wǎng)頁內(nèi)容以及各種圖片,非常之方便。
Scrapy 使用了 Twisted'twɪstɪd異步網(wǎng)絡(luò)框架來處理網(wǎng)絡(luò)通訊,可以加快我們的下載速度,不用自己去實現(xiàn)異步框架,并且包含了各種中間件接口,可以靈活的完成各種需求。


  • Scrapy Engine(引擎): 負(fù)責(zé)Spider、ItemPipeline、Downloader、Scheduler中間的通訊,信號、數(shù)據(jù)傳遞等。
  • Scheduler(調(diào)度器): 它負(fù)責(zé)接受引擎發(fā)送過來的Request請求,并按照一定的方式進(jìn)行整理排列,入隊,當(dāng)引擎需要時,交還給引擎。
  • Downloader(下載器):負(fù)責(zé)下載Scrapy Engine(引擎)發(fā)送的所有Requests請求,并將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理,
  • Spider(爬蟲):它負(fù)責(zé)處理所有Responses,從中分析提取數(shù)據(jù),獲取Item字段需要的數(shù)據(jù),并將需要跟進(jìn)的URL提交給引擎,再次進(jìn)入Scheduler(調(diào)度器),
  • Item Pipeline(管道):它負(fù)責(zé)處理Spider中獲取到的Item,并進(jìn)行進(jìn)行后期處理(詳細(xì)分析、過濾、存儲等)的地方.
  • Downloader Middlewares(下載中間件):你可以當(dāng)作是一個可以自定義擴(kuò)展下載功能的組件。
  • Spider Middlewares(Spider中間件):你可以理解為是一個可以自定擴(kuò)展和操作引擎和Spider中間通信的功能組件(比如進(jìn)入Spider的Responses;和從Spider出去的Requests)

2、Puppeteer渲染

Puppeteer 是 Chrome 開發(fā)團(tuán)隊在 2017 年發(fā)布的一個 Node.js 包,用來模擬 Chrome 瀏覽器的運行。
為了爬取js渲染的html頁面,我們需要用瀏覽器來解析js后生成html。在scrapy中可以利用pyppeteer來實現(xiàn)對應(yīng)功能。
完整代碼 📎scrapy-pyppeteer.zip
我們需要新建項目中middlewares.py文件(./項目名/middlewares.py)

import websockets
from scrapy.http import HtmlResponse
from logging import getLogger
import asyncio
import pyppeteer
import logging
from concurrent.futures._base import TimeoutError
import base64
import sys
import random

pyppeteer_level = logging.WARNING
logging.getLogger('websockets.protocol').setLevel(pyppeteer_level)
logging.getLogger('pyppeteer').setLevel(pyppeteer_level)

PY3 = sys.version_info[0] >= 3


def base64ify(bytes_or_str):
  if PY3 and isinstance(bytes_or_str, str):
    input_bytes = bytes_or_str.encode('utf8')
  else:
    input_bytes = bytes_or_str

  output_bytes = base64.urlsafe_b64encode(input_bytes)
  if PY3:
    return output_bytes.decode('ascii')
  else:
    return output_bytes


class ProxyMiddleware(object):
  USER_AGENT = open('useragents.txt').readlines()

  def process_request(self, request, spider):
    # 代理服務(wù)器
    proxyHost = "t.16yun.cn"
    proxyPort = "31111"
    # 代理隧道驗證信息
    proxyUser = "username"
    proxyPass = "password"

    request.meta['proxy'] = "http://{0}:{1}".format(proxyHost, proxyPort)

    # 添加驗證頭
    encoded_user_pass = base64ify(proxyUser + ":" + proxyPass)
    request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass

    # 設(shè)置IP切換頭(根據(jù)需求)
    tunnel = random.randint(1, 10000)
    request.headers['Proxy-Tunnel'] = str(tunnel)
    request.headers['User-Agent'] = random.choice(self.USER_AGENT)


class PyppeteerMiddleware(object):
  def __init__(self, **args):
    """
    init logger, loop, browser
    :param args:
    """
    self.logger = getLogger(__name__)
    self.loop = asyncio.get_event_loop()
    self.browser = self.loop.run_until_complete(
      pyppeteer.launch(headless=True))
    self.args = args

  def __del__(self):
    """
    close loop
    :return:
    """
    self.loop.close()

  def render(self, url, retries=1, script=None, wait=0.3, scrolldown=False, sleep=0,
        timeout=8.0, keep_page=False):
    """
    render page with pyppeteer
    :param url: page url
    :param retries: max retry times
    :param script: js script to evaluate
    :param wait: number of seconds to wait before loading the page, preventing timeouts
    :param scrolldown: how many times to page down
    :param sleep: how many long to sleep after initial render
    :param timeout: the longest wait time, otherwise raise timeout error
    :param keep_page: keep page not to be closed, browser object needed
    :param browser: pyppetter browser object
    :param with_result: return with js evaluation result
    :return: content, [result]
    """

    # define async render
    async def async_render(url, script, scrolldown, sleep, wait, timeout, keep_page):
      try:
        # basic render
        page = await self.browser.newPage()
        await asyncio.sleep(wait)
        response = await page.goto(url, options={'timeout': int(timeout * 1000)})
        if response.status != 200:
          return None, None, response.status
        result = None
        # evaluate with script
        if script:
          result = await page.evaluate(script)

        # scroll down for {scrolldown} times
        if scrolldown:
          for _ in range(scrolldown):
            await page._keyboard.down('PageDown')
            await asyncio.sleep(sleep)
        else:
          await asyncio.sleep(sleep)
        if scrolldown:
          await page._keyboard.up('PageDown')

        # get html of page
        content = await page.content()

        return content, result, response.status
      except TimeoutError:
        return None, None, 500
      finally:
        # if keep page, do not close it
        if not keep_page:
          await page.close()

    content, result, status = [None] * 3

    # retry for {retries} times
    for i in range(retries):
      if not content:
        content, result, status = self.loop.run_until_complete(
          async_render(url=url, script=script, sleep=sleep, wait=wait,
                 scrolldown=scrolldown, timeout=timeout, keep_page=keep_page))
      else:
        break

    # if need to return js evaluation result
    return content, result, status

  def process_request(self, request, spider):
    """
    :param request: request object
    :param spider: spider object
    :return: HtmlResponse
    """
    if request.meta.get('render'):
      try:
        self.logger.debug('rendering %s', request.url)
        html, result, status = self.render(request.url)
        return HtmlResponse(url=request.url, body=html, request=request, encoding='utf-8',
                  status=status)
      except websockets.exceptions.ConnectionClosed:
        pass

  @classmethod
  def from_crawler(cls, crawler):
    return cls(**crawler.settings.get('PYPPETEER_ARGS', {}))

然后修改項目配置文件 (./項目名/settings.py)

DOWNLOADER_MIDDLEWARES = {
    'scrapypyppeteer.middlewares.PyppeteerMiddleware': 543,
    'scrapypyppeteer.middlewares.ProxyMiddleware': 100,    
  }

然后我們運行程序

到此這篇關(guān)于Scrapy框架介紹之Puppeteer渲染的使用的文章就介紹到這了,更多相關(guān)Scrapy Puppeteer渲染內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Pytest框架之fixture的詳細(xì)使用教程

    Pytest框架之fixture的詳細(xì)使用教程

    這篇文章主要介紹了Pytest框架之fixture的詳細(xì)使用教程,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • 基于Python編寫一個詞云制作程序

    基于Python編寫一個詞云制作程序

    這篇文章主要為大家詳細(xì)介紹了如何基于Python編寫一個簡單的詞云制作程序,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解一下
    2023-10-10
  • Python實現(xiàn)FTP上傳文件或文件夾實例(遞歸)

    Python實現(xiàn)FTP上傳文件或文件夾實例(遞歸)

    本篇文章主要介紹了Python實現(xiàn)FTP上傳文件或文件夾實例(遞歸),具有一定的參考價值,有興趣的可以了解一下。
    2017-01-01
  • Anaconda徹底刪除虛擬環(huán)境的正確方法

    Anaconda徹底刪除虛擬環(huán)境的正確方法

    這篇文章主要給大家介紹了關(guān)于Anaconda徹底刪除虛擬環(huán)境的正確方法,要在Anaconda中刪除一個虛擬環(huán)境,可以按照本文以下步驟進(jìn)行操作,需要的朋友可以參考下
    2023-10-10
  • python中文件導(dǎo)入的使用(在同一目錄下和在不同目錄下)

    python中文件導(dǎo)入的使用(在同一目錄下和在不同目錄下)

    在Python中,使用pathlib模塊的Path類可以方便地導(dǎo)入不同目錄下的文件,本文就來介紹一下,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • python破解同事的壓縮包密碼

    python破解同事的壓縮包密碼

    這篇文章主要介紹了python如何破解壓縮包密碼,幫助大家更好的利用python處理文件,感興趣的朋友可以了解下
    2020-10-10
  • Python代碼實現(xiàn)雙鏈表

    Python代碼實現(xiàn)雙鏈表

    這篇文章主要為大家詳細(xì)介紹了Python代碼實現(xiàn)雙鏈表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Django自定義用戶登錄認(rèn)證示例代碼

    Django自定義用戶登錄認(rèn)證示例代碼

    這篇文章主要給大家介紹了關(guān)于Django自定義用戶登錄認(rèn)證的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Django具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • 基于Flask實現(xiàn)文件上傳七牛云中并下載

    基于Flask實現(xiàn)文件上傳七牛云中并下載

    文件上傳是Web應(yīng)用中常見的功能之一,而七牛云則提供了強(qiáng)大的云存儲服務(wù),本文我們將學(xué)習(xí)如何在Flask應(yīng)用中實現(xiàn)文件上傳,并將上傳的文件保存到七牛云,感興趣的可以學(xué)習(xí)一下
    2023-10-10
  • java關(guān)于string最常出現(xiàn)的面試題整理

    java關(guān)于string最常出現(xiàn)的面試題整理

    在本篇文章里小編給大家整理的是一篇關(guān)于java關(guān)于string最常出現(xiàn)的面試題整理內(nèi)容,有興趣的朋友們可以參考下。
    2021-01-01

最新評論

弥勒县| 云林县| 新竹县| 三亚市| 遂川县| 尉犁县| 丹阳市| 汝南县| 水城县| 屏边| 嵊泗县| 重庆市| 顺平县| 遂川县| 寿宁县| 东海县| 安溪县| 颍上县| 龙泉市| 望城县| 曲麻莱县| 柳林县| 高邑县| 中西区| 凯里市| 望城县| 潮州市| 明光市| 阿拉善右旗| 微山县| 建始县| 依安县| 洛南县| 镇巴县| 定南县| 新疆| 普宁市| 文成县| 礼泉县| 凤山县| 铜鼓县|