Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 一区二区三区久久,中文字幕一区二区三区视频在线,日韩一级黄色片

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          網(wǎng)頁設(shè)計師給自己的兒子取名為“HTML”

          英國《太陽報》報道,菲律賓一位網(wǎng)頁設(shè)計師為了向自己的職業(yè)致敬,給自己的兒子取名為“Hypertext Mark-up Language(超文本標(biāo)記語言)”。這位叫做Mac Pascual的父親表示,給新生兒取個獨(dú)一無二的名字是他們家族的傳統(tǒng)。他對自己的工作充滿熱情,決定給自己的寶寶取名為HTML。據(jù)媒體報道,這個寶寶出生在當(dāng)?shù)氐牟祭册t(yī)療集團(tuán)合作醫(yī)院,體重2.25公斤。

          6月10日,HTML的姑姑Salie Rayo Pascual拍下了這個可愛侄子的照片,并把照片發(fā)布到了Facebook上,標(biāo)題是“HTML,歡迎來到這個世界”。這篇帖子很快引起了網(wǎng)友們的關(guān)注,大家紛紛評論并轉(zhuǎn)發(fā)了這個帖子。不過,還是有一些社交媒體用戶對這個奇特的名字進(jìn)行了一番嘲笑,并嘲諷般地建議他給未來的孩子用一些其他的編碼縮寫來當(dāng)名字,比如“Results-based management system”、“JavaScript”,或者是“Cascading Style Sheets(CSS)”。還有人對寶寶的名字表示了擔(dān)憂評論道:“將來,他可能會成為被欺負(fù)和被嘲笑的對象。”

          HTML的爸爸解釋說,他自己的名字“Mac”就是“Macaroni'85”的縮寫,而他姐姐的名字是“Spaghetti'88(意大利面)”的縮寫。他的姐姐有兩個孩子,分別叫“Cheese Pimiento(辣椒奶酪)”和“Parmesan Cheese(帕爾瑪奶酪)”,所以他們的小名分別是“Chippy”和“Peewee”。HTML和其他名字不同尋常的嬰兒一樣,從出生起就成為了人們討論的話題。特斯拉的首席執(zhí)行官Elon Musk和Claire Boucher(Grimes)就給自己的兒子取名為“X ? A-12 Musk”,因而上了新聞頭條。今年早些時候,模特兼女演員Emily Ratajkowski 通過社交媒體宣布,她將給自己剛出生的寶寶取名為“Sylvester Apollo Bear”。(中國青年網(wǎng)編譯報道)

          來源:中國青年網(wǎng)

          何保持頁面樣式基本不變的前提下將HTML頁面導(dǎo)出為PDF,下面提供一些示例代碼,純屬個人原創(chuàng),如對你有幫助請記得加關(guān)注、加收藏、點(diǎn)贊、轉(zhuǎn)發(fā)、分享~謝謝~~

          • 基本思路:保持頁面樣式基本不變,使用 `html2canvas` 將頁面轉(zhuǎn)換為圖片,然后再通過 `jspdf` 將圖片分頁導(dǎo)出為PDF文件(中間會遇到圖片或文字等內(nèi)容在分頁處被切割開的問題,如何解決了?詳見末尾干貨)
          • 上基礎(chǔ)代碼:下面為項目中實(shí)際代碼截取
          <div>
              <!-- 要打印的內(nèi)容區(qū) -->
              <div ref="contentRef">
                  <div class="print-item print-out-flow">這是脫離文檔流的內(nèi)容區(qū)域</div>
                  <div class="print-item">這是一行內(nèi)容,也是最小葉子元素內(nèi)容</div>
              </div>
              <!-- 打印內(nèi)容容器 -->
              <div ref="printContainerRef" class="print-container"></div>
          </div>
          /**
            * 1.使用一個隱藏div裝載有滾動條的div.innerHTML
            * 2.隱藏div使用position: absolute, z-index: -999, left: -9999px, width: 900px 控制讓用戶無感知
            * 3.根據(jù)需要覆寫隱藏div內(nèi)html樣式(例如textarea多行顯示有問題, 可以新增一個隱藏的div
            *    包裹textarea的綁定值, 然后在打印樣式中覆寫樣式, 隱藏textarea并顯示對應(yīng)div)
            */
          handleExport() {
             // 下面是VUE組件內(nèi)獲取DOM元素代碼,將內(nèi)容放置到打印區(qū)(定義的隱藏DIV)中
              const contentRef = this.$refs.contentRef as HTMLElement;
              const printContainerRef = this.$refs.printContainerRef as HTMLElement;
              // 打印區(qū)的需額外處理絕對定位值, 調(diào)整使得第一個元素的.top值為0, 以便于頁面計算
              printContainerRef.innerHTML = contentRef.innerHTML;	
              
              // 所有葉子div元素加上 print-item 樣式名, 脫離文檔流的額外添加 print-out-flow
              handlePrintItem(printContainerRef);  // 解決多頁內(nèi)容可能被切割問題
              
              html2canvas(printContainerRef, {allowTaint: false, useCORS: true}).then((canvas: any) => {
                const contentHeight = canvas.height;
                const contentWidth = canvas.width;
                // pdf每頁顯示的內(nèi)容高度
                const pageHeight = contentWidth / 595.28 * 841.89;
                // 未生成pdf的頁面高度
                let offsetHeight = contentHeight;
                // 頁面偏移值
                let position = 0;
                // a4紙的尺寸[595.28, 841.89], canvas圖片按a4紙大小縮放后的寬高
                const imgWidth = 595.28;
                const imgHeight = 595.28 / contentWidth * contentHeight;
          
                const dataURL = canvas.toDataURL('image/jpeg', 1.0);
                const doc = new jsPDF('p', 'pt', 'a4');
          
                if (offsetHeight < pageHeight) {
                  doc.addImage(dataURL, 'JPEG', 0, 0, imgWidth, imgHeight);
                } else {
                  while (offsetHeight > 0) {
                    doc.addImage(dataURL, 'JPEG', 0, position, imgWidth, imgHeight);
                    offsetHeight -= pageHeight;
                    position -= 841.89;
          
                    if (offsetHeight > 0) {
                      doc.addPage();
                    }
                  }
                }
          
                doc.save(this.generateReportFileName());
                printContainerRef.innerHTML = '';
              });
          }

          上干貨代碼:上面分頁導(dǎo)出PDF可能網(wǎng)上能看到類型代碼,但絕對找不到下面的代碼,純手搓解決分頁元素被切開問題(思路:獲取自身定位,如自己剛好在被分頁處,則加上一定的margin-top值將內(nèi)容向下移)

          /** 
           * 處理打印元素項, 修復(fù)分頁后被切割的元素
           * @param printContainerRef 打印內(nèi)容div容器
           * @param itemClassName 打印最小元素標(biāo)識類名
           * @param outFlowClassName 脫離文檔流的元素標(biāo)識類名
           */
          export function handlePrintItem(
            printContainerRef: HTMLElement,
            itemClassName: string = 'print-item',
            outFlowClassName: string = 'print-out-flow'
          ): void {
            const rootClientRect = printContainerRef.getBoundingClientRect();
            // 初始化頁面相關(guān)數(shù)據(jù)
            const totalHeight = rootClientRect.height;  // 內(nèi)容總高度
            const a4PageHeight = (printContainerRef.clientWidth / 595.28) * 841.89; // a4紙高度
            let pageNum = Math.ceil(totalHeight / a4PageHeight);  // 總頁數(shù)
            let addPageHeight = 0;  // 修正被分割元素而增加的頁面高度總和
            let currentPage = 1;  // 當(dāng)前正在處理切割的頁面
            const splitItemObj: { [key: number]: HTMLElement[] } = {};  // 內(nèi)容中各頁被切割元素存儲對象
          
            const printItemNodes: NodeListOf<HTMLElement> = printContainerRef.querySelectorAll(`.${itemClassName}`);
            for (let item of printItemNodes) {
              // 如果當(dāng)前頁已經(jīng)是最后一頁, 則中斷判斷
              if (currentPage >= pageNum) {
                break;
              }
          
              // 獲取元素絕對定位數(shù)據(jù)
              const clientRect = item.getBoundingClientRect();
              let top = clientRect.top;
              const selfHeight = clientRect.height;
              // 如果當(dāng)前元素距離頂部高度大于當(dāng)前頁面頁腳高度, 則開始判斷下一頁頁腳被切割元素
              if (top > currentPage * a4PageHeight) {
                // 換頁前修正上一頁被切割元素
                addPageHeight += fixSplitItems(currentPage, a4PageHeight, splitItemObj[currentPage], outFlowClassName);
                pageNum = Math.ceil((totalHeight + addPageHeight) / a4PageHeight);
                top = item.getBoundingClientRect().top;
                currentPage++;
              }
              // 如果元素剛好處于兩頁之間, 則記錄該元素
              if (top > (currentPage - 1) * a4PageHeight && top < currentPage * a4PageHeight && top + selfHeight > currentPage * a4PageHeight) {
                if (!splitItemObj[currentPage]) {
                  splitItemObj[currentPage] = [];
                }
                splitItemObj[currentPage].unshift(item);
                // 如果當(dāng)前元素是最后一個元素, 則直接處理切割元素, 否則交由處理下一頁元素時再處理切割
                if (item === printItemNodes[printItemNodes.length - 1]) {
                  fixSplitItems(currentPage, a4PageHeight, splitItemObj[currentPage], outFlowClassName);
                }
              }
            }
          }
          
          /**
            * 修復(fù)當(dāng)前頁所有被切割元素
            * @param currentPage 當(dāng)前頁
            * @param pageHeight 每頁高度
            * @param splitElementItems 當(dāng)前被切割元素數(shù)組
            * @param outFlowClassName 脫離文檔流的樣式類名
            */
          function fixSplitItems(
            currentPage: number,
            pageHeight: number,
            splitElementItems: HTMLElement[],
            outFlowClassName: string
          ): number {
            if (!splitElementItems || !splitElementItems.length) {
              return 0;
            }
          
            const yMargin = 5;  // y方向距離頁眉的距離
            const splitItemsMinTop = getSplitItemsMinTop(splitElementItems);
            if (!splitItemsMinTop) {
              return 0;
            }
          
            let fixHeight = currentPage * pageHeight - splitItemsMinTop + yMargin;
            const outFlowElement = splitElementItems.find((item) => item.classList.contains(outFlowClassName));
            if (outFlowElement && outFlowElement.parentElement) {
              const parentPreviousElement = outFlowElement.parentElement.previousElementSibling as HTMLElement;
              fixHeight += getMarinTopNum(parentPreviousElement, outFlowElement.parentElement);
              outFlowElement.parentElement.style.marginTop = `${fixHeight}px`;
              return fixHeight;
            }
          
            splitElementItems.forEach((splitElement) => {
              splitElement.style.marginTop = `${fixHeight}px`;
            });
            return fixHeight;
          }
          
          /**
            * 獲取被切割元素數(shù)組中最小高度值(如一行有多個元素被切割,則選出距離頂部最小的高度值)
            * @param splitElementItems 當(dāng)前被切割元素數(shù)組
            */
          function getSplitItemsMinTop(
            splitElementItems: HTMLElement[]
          ): number | undefined {
            // 獲取元素中最小top值作為基準(zhǔn)進(jìn)行修正
            let minTop: number | undefined;
            let minElement: HTMLElement | undefined;
            splitElementItems.forEach((splitElement) => {
              let top = splitElement.getBoundingClientRect().top;
              if (minTop) {
                minTop = top < minTop ? top : minTop;
                minElement = top < minTop ? splitElement : minElement;
              } else {
                minTop = top;
                minElement = splitElement;
              }
            });
          
            // 修正當(dāng)前節(jié)點(diǎn)及其前面同層級節(jié)點(diǎn)的margin值
            if (minTop && minElement) {
              const previousElement = splitElementItems[splitElementItems.length - 1].previousElementSibling as HTMLElement;
              minTop -= getMarinTopNum(previousElement, minElement);
            }
            return minTop;
          }
          
          /**
            * 通過前一個兄弟元素和元素自身的位置確認(rèn)一個距離頂部高度修正值
            * @param previousElement 前一個兄弟元素
            * @param curElement 當(dāng)前元素
            */
          function getMarinTopNum(previousElement: HTMLElement, curElement: HTMLElement): number {
            let preMarginNum = 0;
            let curMarginNum = 0;
            if (previousElement) {
              // 獲取外聯(lián)樣式需要getComputedStyle(), 直接.style時對象的值都為空
              const previousMarginBottom = window.getComputedStyle(previousElement).marginBottom;
              preMarginNum = previousMarginBottom ? Number(previousMarginBottom.replace('px', '')) : 0;
            }
            const marginTop = window.getComputedStyle(curElement).marginTop;
            curMarginNum = marginTop ? Number(marginTop.replace('px', '')) : 0;
            return preMarginNum > curMarginNum ? preMarginNum : curMarginNum;
          }

          以上純原創(chuàng)!歡迎加關(guān)注、加收藏、點(diǎn)贊、轉(zhuǎn)發(fā)、分享(代碼閑聊站)~

          近臨近開學(xué)了,大家都在忙著準(zhǔn)備各種學(xué)習(xí)的資料,準(zhǔn)備在新的學(xué)期好好學(xué)習(xí),充實(shí)自己。小編身邊的同學(xué)也是如此,最近,小編的同學(xué)小麗就遇到了一個很棘手的問題。

          她想將一個網(wǎng)頁的Python學(xué)習(xí)的教程打印下來,方便自己來學(xué)習(xí),但是上千頁的教程,如果通過手動的方式,一個一個的去轉(zhuǎn)成pdf并保存到本地,實(shí)在是麻煩的不。

          這就是一個html轉(zhuǎn)pdf的問題,其實(shí)網(wǎng)上有很多不錯的html資源,但是苦于學(xué)習(xí)起來,不方便!于是小編就跟小麗保證,這點(diǎn)小事包在我身上。今天,小編就跟分享一下如何用Python把html資料變成pdf。

          01.抓取的學(xué)習(xí)資料

          如今網(wǎng)上的在線學(xué)習(xí)資料可謂是多如牛毛,為了方便講解,小編就利用python3.9.2的中文文檔作為演示的例子,來將其抓取并保存到本地,其網(wǎng)頁鏈接如下:

          https://docs.python.org/zh-cn/3.9/tutorial/index.html

          打開上述鏈接后,大家會在網(wǎng)頁中找到不同內(nèi)容的鏈接地址,包括了基礎(chǔ)的python字符、python語法等內(nèi)容。

          02.獲取網(wǎng)頁鏈接

          在上圖中,我們需要格外關(guān)注的是紅色方格標(biāo)注的鏈接,每個鏈接都會跳轉(zhuǎn)到對應(yīng)的子網(wǎng)頁中,而在子網(wǎng)頁中,就是我們想要保存的內(nèi)容。

          可以看到,上圖中,在python速覽子頁面中,包含了我們需要提取的文字內(nèi)容。所以將html內(nèi)容保存為pdf的第一步便是獲取到子頁面的鏈接。由于教程大都是固定內(nèi)容,因此對于教程的網(wǎng)頁,大都采用的是靜態(tài)頁面,在網(wǎng)頁源代碼中可以很輕松地找到子頁面的網(wǎng)頁鏈接。

          對于子網(wǎng)頁的鏈接抓取,程序如下圖所示:

          程序中,通過BeautifulSoup庫來解析網(wǎng)頁源代碼,然后提取所有的子頁面鏈接地址并返回,如果抓取失敗,則直接返回None


          03.html轉(zhuǎn)pdf

          在得到子網(wǎng)頁的鏈接后,接下來就是將html的子網(wǎng)頁保存為pdf文件。小編使用的pdfkit庫,pdfkit庫可以將網(wǎng)頁保存為pdf文檔。首先小編來介紹一下pdfkit庫的安裝。

          • 下載https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox-0.12.6-1.mxe-cross-win64.7z 并解壓到本地文件中。(后臺輸入:pdf) 直接獲取。
          • 將解壓文件中的bin文件路徑添加到系統(tǒng)變量Path中。
          • 執(zhí)行pip install pdfkit
          • 執(zhí)行pip install wkhtmltopdf

          按照上述的操作流程,就可以安裝pdfkit庫。對于pdfkit庫的使用,常見的用法有以下三種:

          上面的程序主要完成以下幾步:

          首先需要指定wkhtmltopdf.exe文件的路徑;

          • 然后分別通過from_url、from_file和from_string的三種方式來保存為pdf文件;
          • 需要注意的是,from_file和from_url中的第一個參數(shù)必須是一個html的字符串或者是html文檔的列表;
          • 但是小編通過程序運(yùn)行發(fā)現(xiàn),from_url第一個參數(shù)只能是html的字符串,不能是html的列表


          因此,pdfkit庫只能將子網(wǎng)頁保存為單獨(dú)的pdf文檔,無法直接通過pdfkit庫將所有的子網(wǎng)頁拼接成一個完整的pdf文檔,小編通過PyPDF2庫中的PdfFileMerger類來實(shí)現(xiàn)pdf文檔的拼接。程序如下圖所示。

          程序中首先將所有的html網(wǎng)頁保存為單獨(dú)的pdf文檔,然后通過PdfFileMerger類對象來實(shí)現(xiàn)pdf文檔的拼接。最后就可以得到全部的pdf內(nèi)容。最后我們通過視頻的展示,來看一下程序的效果吧。


          除此之外,程序不光可以抓取python3.9的中文文檔,針對其他的在線文檔,只需要對獲取網(wǎng)頁鏈接的程序進(jìn)行修改即可抓取,例如對于Flask中文文檔的抓取,程序只需要按照下圖進(jìn)行修改,即可將Flask的在線文檔保存為PDF文檔。

          04.總結(jié)

          學(xué)習(xí)Python其實(shí)非常有趣,也很有用。因為Python有大量的現(xiàn)成的庫,可以幫助我們把工作中的很多瑣碎的煩事輕松解決。小編將上述的程序稍加修改,很快就幫阿麗搞定了教程,保存為pdf發(fā)送給了她,小編與女神的關(guān)系更拉近了一步


          主站蜘蛛池模板: 一区二区三区四区精品| 亚洲高清美女一区二区三区| 免费无码毛片一区二区APP| 美女福利视频一区二区| 99久久精品国产一区二区成人| 四虎永久在线精品免费一区二区 | 久夜色精品国产一区二区三区| 亚洲日韩中文字幕一区| 久久久久人妻一区二区三区vr| 2014AV天堂无码一区| 一区二区三区免费高清视频| 国产第一区二区三区在线观看| 亚洲av无码一区二区三区人妖 | 亚洲欧美一区二区三区日产| 国产精品视频一区二区三区无码| 一区二区三区视频观看| 男人免费视频一区二区在线观看| 五十路熟女人妻一区二区| 精品黑人一区二区三区| 亚欧在线精品免费观看一区| 99久久精品国产一区二区成人| 人妻AV一区二区三区精品| 久久91精品国产一区二区| 国产精品无圣光一区二区| 精品一区二区三区中文字幕| 中文字幕在线精品视频入口一区| 中文字幕一区二区三区在线播放| www一区二区www免费| 中文字幕精品无码一区二区| 精品国产免费一区二区三区香蕉| 国产福利视频一区二区| 亚洲线精品一区二区三区影音先锋 | 国产成人一区二区三中文| 在线观看一区二区三区av| 日韩视频一区二区在线观看| 波多野结衣在线观看一区二区三区| 国产麻豆剧果冻传媒一区| 国产成人久久精品麻豆一区| 日韩一区二区久久久久久| 亚洲国产一区在线观看| 成人一区二区三区视频在线观看|