迎點擊右上角關(guān)注小編,除了分享技術(shù)文章之外還有很多福利,私信學(xué)習(xí)資料可以領(lǐng)取包括不限于Python實戰(zhàn)演練、PDF電子文檔、面試集錦、學(xué)習(xí)資料等。
想要把教程變成PDF有三步:
1、先生成空html,爬取每一篇教程放進一個新生成的div,這樣就生成了包含所有教程的html文件(BeautifulSoup)
2、將html轉(zhuǎn)換成pdf(wkhtmltopdf)
3、由于反爬做的比較好,在爬取的過程中還需要代理ip(免費 or 付費)
開始使用
將一段文檔傳入 BeautifulSoup 的構(gòu)造方法,就能得到一個文檔的對象, 可以傳入一段字符串或一個文件句柄.
如下所示:
首先,文檔被轉(zhuǎn)換成Unicode,并且HTML的實例都被轉(zhuǎn)換成Unicode編碼.
然后,Beautiful Soup選擇最合適的解析器來解析這段文檔,如果手動指定解析器那么Beautiful Soup會選擇指定的解析器來解析文檔.
對象的種類
Beautiful Soup 將復(fù)雜 HTML 文檔轉(zhuǎn)換成一個復(fù)雜的樹形結(jié)構(gòu),每個節(jié)點都是 Python 對象,所有對象可以歸納為 4 種: Tag , NavigableString , BeautifulSoup , Comment .
Tag:通俗點講就是 HTML 中的一個個標簽,類似 div,p。
NavigableString:獲取標簽內(nèi)部的文字,如,soup.p.string。
BeautifulSoup:表示一個文檔的全部內(nèi)容。
Comment:Comment 對象是一個特殊類型的 NavigableString 對象,其輸出的內(nèi)容不包括注釋符號.
Tag
Tag就是html中的一個標簽,用BeautifulSoup就能解析出來Tag的具體內(nèi)容,具體的格式為soup.name,其中name是html下的標簽,具體實例如下:
print soup.title輸出title標簽下的內(nèi)容,包括此標簽,這個將會輸出
print soup.head輸出head標簽下的內(nèi)容
如果 Tag 對象要獲取的標簽有多個的話,它只會返回所以內(nèi)容中第一個符合要求的標簽。
Tag 屬性
每個 Tag 有兩個重要的屬性 name 和 attrs:
name:對于Tag,它的name就是其本身,如soup.p.name就是p
attrs是一個字典類型的,對應(yīng)的是屬性-值,如print soup.p.attrs,輸出的就是{'class': ['title'], 'name': 'dromouse'},當(dāng)然你也可以得到具體的值,如print soup.p.attrs['class'],輸出的就是[title]是一個列表的類型,因為一個屬性可能對應(yīng)多個值,當(dāng)然你也可以通過get方法得到屬性的,如:print soup.p.get('class')。還可以直接使用print soup.p['class']
get
get方法用于得到標簽下的屬性值,注意這是一個重要的方法,在許多場合都能用到,比如你要得到<img src="#">標簽下的圖像url,那么就可以用soup.img.get('src'),具體解析如下:
# 得到第一個p標簽下的src屬性printsoup.p.get("class")
string
得到標簽下的文本內(nèi)容,只有在此標簽下沒有子標簽,或者只有一個子標簽的情況下才能返回其中的內(nèi)容,否則返回的是None具體實例如下:
# 在上面的一段文本中p標簽沒有子標簽,因此能夠正確返回文本的內(nèi)容printsoup.p.string# 這里得到的就是None,因為這里的html中有很多的子標簽printsoup.html.string
get_text()
可以獲得一個標簽中的所有文本內(nèi)容,包括子孫節(jié)點的內(nèi)容,這是最常用的方法。
搜索文檔樹
BeautifulSoup 主要用來遍歷子節(jié)點及子節(jié)點的屬性,通過Tag取屬性的方式只能獲得當(dāng)前文檔中的第一個 tag,例如,soup.p。如果想要得到所有的<p> 標簽,或是通過名字得到比一個 tag 更多的內(nèi)容的時候,就需要用到 find_all()
find_all(name, attrs, recursive, text, **kwargs )
find_all是用于搜索節(jié)點中所有符合過濾條件的節(jié)點。
name參數(shù):是Tag的名字,如p,div,title
# 1. 節(jié)點名print(soup.find_all('p'))# 2. 正則表達式print(soup.find_all(re.compile('^p')))# 3. 列表 print(soup.find_all(['p','a']))
另外 attrs 參數(shù)可以也作為過濾條件來獲取內(nèi)容,而 limit 參數(shù)是限制返回的條數(shù)。
CSS 選擇器
以 CSS 語法為匹配標準找到 Tag。同樣也是使用到一個函數(shù),該函數(shù)為select(),返回類型是 list。它的具體用法如下:
# 1. 通過 tag 標簽查找print(soup.select(head))# 2. 通過 id 查找print(soup.select('#link1'))# 3. 通過 class 查找print(soup.select('.sister'))# 4. 通過屬性查找print(soup.select('p[name=dromouse]'))# 5. 組合查找print(soup.select("body p"))
wkhtmltopdf
wkhtmltopdf主要用于HTML生成PDF。
pdfkit是基于wkhtmltopdf的python封裝,支持URL,本地文件,文本內(nèi)容到PDF的轉(zhuǎn)換,其最終還是調(diào)用wkhtmltopdf命令。
安裝
先安裝wkhtmltopdf,再安裝pdfkit。
https://wkhtmltopdf.org/downloads.html
pdfkit
shell pip3 install pdfkit
轉(zhuǎn)換url/file/string
importpdfkitpdfkit.from_url('http://google.com','out.pdf')pdfkit.from_file('index.html','out.pdf')pdfkit.from_string('Hello!','out.pdf')
轉(zhuǎn)換url或者文件名列表
pdfkit.from_url(['google.com','baidu.com'],'out.pdf')pdfkit.from_file(['file1.html','file2.html'],'out.pdf')
轉(zhuǎn)換打開文件
withopen('file.html')asf: pdfkit.from_file(f,'out.pdf')
自定義設(shè)置
使用代理ip
爬取十幾篇教程之后觸發(fā)了這個錯誤:
看來廖大的反爬蟲做的很好,于是只好使用代理ip了,嘗試了免費的西刺免費代理后,最后選擇了付費的 阿布云 ,感覺響應(yīng)速度和穩(wěn)定性還OK。
運行結(jié)果
運行過程截圖:
運行過程
生成的效果圖:
效果圖
代碼如下:
Pandas非常善于處理大量數(shù)據(jù)并在多個文本和可視化表示中對其進行匯總。支持輸出到CSV,Excel,HTML,json等。如果想將多個數(shù)據(jù)組合到一個文檔中,那么會有點困難。例如,如果要在一個Excel工作表上放置兩個DataFrame,則需要使用Excel庫手動構(gòu)建輸出。
5分鐘教您用python生成精美的PDF文檔
本文將介紹如何將多條信息組合成一個HTML模板,然后使用和將其轉(zhuǎn)換為精美的PDF文檔。
下面看看生成的PDF效果吧:
5分鐘教您用python生成精美的PDF文檔效果
使用Pandas將數(shù)據(jù)輸出到Excel文件中的多個工作表或從pandas DataFrames創(chuàng)建多個Excel文件非常方便。但是,如果您想將多個信息組合到一個文件中,那么直接從Pandas完成它的方法并不多。幸運的是,python有很多工具可以辦到。
在本文中,將使用通過以下流程來創(chuàng)建多頁PDF 文檔。
將使用通過以下流程來創(chuàng)建多頁PDF 文檔
這種方法的好處在于您可以將自己的工具替換為此工作流程。如果您想在HTML之外使用其他類型的標記,請選擇Jinja。
首先,使用HTML作為模板語言,因為它可能是生成結(jié)構(gòu)化數(shù)據(jù)并允許相對豐富的格式化的最簡單方法。每個人都知道(或可以弄清楚)足夠的HTML來生成一個簡單的報告。最困難的部分是弄清楚如何將HTML呈現(xiàn)為PDF。選擇了WeasyPrint,相對而言是最佳解決方案,因為它仍在積極維護,可以相對容易地使用它。另外效果也很好。遺憾的是,此時文檔有點缺乏,確實可以從HTML生成PDF。
下面是導(dǎo)入數(shù)據(jù)并生成數(shù)據(jù)透視表以及CPU和軟件銷售的平均數(shù)量和價格的一些匯總統(tǒng)計數(shù)據(jù)。
導(dǎo)入模塊,并讀入銷售渠道信息。
from __future__ import print_function import pandas as pd import numpy as np df=pd.read_excel("sales-funnel.xlsx") df.head()
透視數(shù)據(jù)進行總結(jié)。
sales_report=pd.pivot_table(df, index=["Manager", "Rep", "Product"], values=["Price", "Quantity"], aggfunc=[np.sum, np.mean], fill_value=0) sales_report.head()
生成有關(guān)整個數(shù)據(jù)集的一些總體描述性統(tǒng)計信息。在這種情況下,我們希望顯示CPU和軟件銷售的平均數(shù)量和價格。
print(df[df["Product"]=="CPU"]["Quantity"].mean()) print(df[df["Product"]=="CPU"]["Price"].mean()) print(df[df["Product"]=="Software"]["Quantity"].mean()) print(df[df["Product"]=="Software"]["Price"].mean()) 1.88888888889 51666.6666667 1.0 10000.0
理想情況下,現(xiàn)在要做的是通過經(jīng)理分組匯總數(shù)據(jù),并在頁面上包含一些摘要統(tǒng)計數(shù)據(jù),以幫助理解單個結(jié)果與全國平均值的比較。
DataFrame選項
幸運的是,DataFrame有一個 to_clipboard() 將整個DataFrame復(fù)制到剪貼板的功能,然后您可以輕松地將其粘貼到Excel中。
稍后將在模板中使用的另一個選項是 to_html() 生成包含一個應(yīng)用了最小樣式的完全組合的HTML表。
模板
Jinja模板功能非常強大,支持許多高級功能,例如沙盒執(zhí)行和自動轉(zhuǎn)義,這些都不是此應(yīng)用程序所必需的。但是,隨著您的報告變得越來越復(fù)雜或您選擇將Jinja用于您的網(wǎng)絡(luò)應(yīng)用,這些功能將為您提供良好的服務(wù)。
Jinja的另一個不錯的功能是它包含多個 ,這些允許我們以Pandas中難以做到的方式格式化我們的一些數(shù)據(jù)。
為了在應(yīng)用程序中使用Jinja,需要做三件事:
· 創(chuàng)建一個模板
· 將變量添加到模板上下文中
· 將模板渲染為HTML
這是一個非常簡單的模板,稱之為myreport.html :
<!DOCTYPE html> < html > < head lang="en" > < meta charset="UTF-8" > < title > {{title}} </ title > </ head > < body > < h2 >銷售漏斗報告 - 國家</ h2 > {{national_pivot_table}} </ body > </ html >
這段代碼的兩個關(guān)鍵部分是 {{ title }} 和 {{ national_pivot_table }} 。它們本質(zhì)上是我們在呈現(xiàn)文檔時將提供的變量的占位符。
要填充這些變量,需要創(chuàng)建一個Jinja環(huán)境并讀取模板:
from jinja2 import Environment, FileSystemLoader env=Environment(loader=FileSystemLoader('.')) template=env.get_template("myreport.html")
在上面的示例中,假設(shè)模板位于當(dāng)前目錄中。
另一個關(guān)鍵組件是創(chuàng)建 env 。這個變量是我們將內(nèi)容傳遞給模板的方式。我們創(chuàng)建一個名為的字典template_var ,其中包含我們想要傳遞給模板的所有變量。
請注意變量的名稱如何與模板匹配。
template_vars={"title" : "Sales Funnel Report - National", "national_pivot_table": sales_report.to_html()}
最后一步是使用輸出中包含的變量呈現(xiàn)HTML。這將創(chuàng)建一個我們最終將傳遞給PDF創(chuàng)建引擎的字符串。
html_out=template.render(template_vars)
為簡潔起見,我不會顯示完整的HTML,但您應(yīng)該明白這一點。
生成PDF
該PDF創(chuàng)建部分比較簡單為好。我們需要進行一些導(dǎo)入并將字符串傳遞給PDF 生成器。
from weasyprint import HTML HTML(string=html_out).write_pdf("report.pdf")
此命令創(chuàng)建一個類似于以下內(nèi)容的PDF報告:
啊。很酷,它是一個PDF,但它很難看。主要問題是沒有加入任何css樣式。
對于本文的其余部分,將使用blue print的作為的style.css的基礎(chǔ),如下所示。這個CSS的是:
· 它相對較小且易于理解
· 它可以在PDF引擎中運行而不會拋出錯誤和警告
· 它包括看起來相當(dāng)不錯的基本表格式
讓我們嘗試使用我們更新的樣式表重新渲染它:
HTML(string=html_out).write_pdf(args.outfile.name, stylesheets=["style.css"])
只需添加一個簡單的樣式表就會產(chǎn)生巨大的差異!
更復(fù)雜的模板
為了生成更有用的報告,將結(jié)合上面顯示的摘要統(tǒng)計信息以及分析報告,以便為每個經(jīng)理包含一個自己單獨的PDF頁面。
讓我們從更新的模板(myreport.html)開始:
<!DOCTYPE html> < html > < head lang="en" > < meta charset="UTF-8" > < title > {{title}} </ title > </ head > < body > < div class="容器" > < h2 >銷售漏斗報告 - 國家</ h2 > {{national_pivot_table}} {%include"summary.html"%} </ div > < div class="container" > {%為經(jīng)理在Manager_Detail%} < p style="page-break-before:always" > </ p > < h2 >銷售渠道報告 - {{manager.0}} </ h2 > {{manager.1}} {%include"summary.html"%} {%endfor%} </ div > </ body > </ html >
你會注意到的第一件事是有一個 include 聲明提到了另一個文件。這 include 允許引入一段HTML并在代碼的不同部分中重復(fù)使用它。在這種情況下,摘要包含希望包含在每個報告中的一些簡單的國家級統(tǒng)計數(shù)據(jù),以便管理人員可以將其績效與全國平均水平進行比較。
這是summary.html的樣子:
< h3 >國家概要:CPU </ h3 > < ul > < li >平均數(shù)量:{{CPU.0 | round(1)}} </ li > < li >平均價格:{{CPU.1 | round( 1)}} </ li > </ ul > < h3 >國家摘要:軟件</ h3 > < ul > < li >平均數(shù)量:{{Software.0 | round(1)}} </ li > < li >平均價格:{{Software.1 | round(1)}} </ li > </ ul >
在此代碼段中,您將看到我們可以訪問的其他變量: CPU 和 Software 。其中每個都是一個python列表,其中包括CPU和軟件銷售的平均數(shù)量和價格。
您可能還注意到我們使用管道 | 將 round 每個值用于1位小數(shù)。這是使用Jinja過濾器的一個具體示例。
還有一個for循環(huán),允許我們在報告中顯示每個經(jīng)理的詳細信息。Jinja的模板語言只包含一小部分改變控制流的代碼。基本for循環(huán)幾乎是任何模板的支柱,因此它們應(yīng)該對大多數(shù)人有意義。
我想調(diào)出一段看起來有點不合適的最后一段代碼:
< p style="page-break-before:always" > </ p >
這是一個簡單的CSS指令,我把它放在每個頁面上以確保CSS中斷。
額外的統(tǒng)計數(shù)據(jù)
現(xiàn)在已經(jīng)完成了模板,這里是如何創(chuàng)建模板中使用的其他上下文變量。
這是一個簡單的匯總函數(shù):
def get_summary_stats(df,product): """ For certain products we want National Summary level information on the reports Return a list of the average quantity and price """ results=[] results.append(df[df["Product"]==product]["Quantity"].mean()) results.append(df[df["Product"]==product]["Price"].mean()) return results
還需要創(chuàng)建經(jīng)理詳細信息:
manager_df=[] for manager in sales_report.index.get_level_values(0).unique(): manager_df.append([manager, sales_report.xs(manager, level=0).to_html()])
最后,使用以下變量調(diào)用模板:
template_vars={"title" : "National Sales Funnel Report", "CPU" : get_summary_stats(df, "CPU"), "Software": get_summary_stats(df, "Software"), "national_pivot_table": sales_report.to_html(), "Manager_Detail": manager_df} # Render our file and create the PDF using our css style file html_out=template.render(template_vars) HTML(string=html_out).write_pdf("report.pdf",stylesheets=["style.css"])
讓python改變生活!如果滿意上面的生成PDF講解,點贊和評論。
獲取文中代碼請微信關(guān)注 "python_dada"公眾號,輸入“精美PDF”獲取。
人都是pythonista
這兩天一直在做課件,我個人一直不太喜歡PPT這個東西……能不用就不用,我個人特別崇尚極簡風(fēng)。
誰讓我們是程序員呢,所以就愛上了Jupyter寫課件,講道理markdown也是個非常不錯的寫書格式啊。
安裝Jupyter其實非常簡單,你會python就應(yīng)該會用jupyter,起碼簡單的 pip install jupyter, jupyter notebook 要會對伐~
好那接下來就是使用jupyter了,啟動jupyter后,使用瀏覽器訪問相應(yīng)IP:Port就可以使用了。沒錯,jupyter就是這么一個可以用網(wǎng)站來寫python的地方。
jupyter notebook
但是發(fā)講義給同學(xué)們看,ipynb格式的文件肯定不方便啊,別人還沒上課呢,哪知道那么多?再者PDF傳閱起來也隨時隨地能打開啊。所以我就想轉(zhuǎn)換成PDF。
但是打開文件,點擊下載,發(fā)現(xiàn)出現(xiàn)了Error
jupyter
jupyter
然后照著這個Error,就去谷歌了,發(fā)現(xiàn)說的最多的就是要裝一個latex環(huán)境,mac下完整的安裝包要將近3個G!我就為了一個PDF還不需要這么大一個包吧?所以尋思其他方法。
雖然jupyter對PDF支持的不是那么的友善,但是對于html是非常棒的,只不過html是一個html嘛(這不是廢話)……不過我可以利用html轉(zhuǎn)換到pdf上啊。
后來了解到python有一個包叫 pdfkit,專門用來轉(zhuǎn)換pdf文件。那我現(xiàn)在只需要在mac上得到pdfkit的支持就好啦?所以接下來就是嘗試的過程了。
1. 安裝pdfkit,pip install pdfkit
2. 在這里下載對應(yīng)系統(tǒng)的安裝包http://wkhtmltopdf.org/,這個只有48MB。
3. 最后就是為什么說python是「多膜優(yōu)秀」的原因了!直接看代碼
python編程
操作起來也很簡單:
jupyter
至此,ipynb文件已成功轉(zhuǎn)換成pdf文件,并且顏色、格式全都保留!
私信我:zsxq06,獲取本文全套代碼!
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。