整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          python爬蟲之Beautiful Soup庫,基

          python爬蟲之Beautiful Soup庫,基本使用以及提取頁面信息

          、Beautiful Soup簡介

          爬蟲正則表達式參考我上一篇文章:Python 爬蟲正則表達式和re庫

          在爬蟲過程中,可以利用正則表達式去提取信息,但是有些人覺得比較麻煩。因為花大量時間分析正則表達式。這時候可以用高效的網頁解析庫Beautiful Soup。

          Beautiful Soup 是一個HTML/XML 的解析器,主要用于解析和提取 HTML/XML 數據。

          Beautiful Soup支持Python標準庫中的HTML解析器,還支持一些第三方的解析器,如果我們不安裝它,則 Python 會使用 Python默認的解析器,lxml 解析器更加強大,速度更快,推薦安裝。

          下面是各種解析器優缺點

          二、Beautiful Soup 安裝

          Beautiful Soup 3 目前已經停止開發,推薦在現在的項目中使用Beautiful Soup 4,不過它已經被移植到BS4了,也就是說導入時我們需要 import bs4。

          安裝Beautiful Soup

          pip install beautifulsoup4

          根據操作系統不同,可以選擇下列方法來安裝lxml,安裝解析器:

          apt-get install Python-lxml
          
          easy_install lxml
          
          pip install lxml

          創建對象時,指定解析器,這里為lxml

          from bs4 import BeautifulSoup
          
          bs=BeautifulSoup(html,"lxml")


          三、Beautiful Soup 使用

          Beautiful Soup將復雜HTML文檔轉換成一個復雜的樹形結構,每個節點都是Python對象,所有對象可以歸納為4種: Tag , NavigableString , BeautifulSoup , Comment .

          (1)Tag

          標簽,最基本的信息組織單元,分別用<>和標明開頭和結尾,通俗點講就是 HTML 中的一個個標簽。

          Tag有很多方法和屬性,tag中最重要的屬性: name和attributes。

          name

          每個tag都有自己的名字,通過 .name 來獲取:

          慣例,同樣以豆瓣電影排行做分析,鏈接為:https://movie.douban.com/top250

          import requests
          from bs4 import BeautifulSoup
          
          headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/65.0.3325.162 Safari/537.36'}
          url='https://movie.douban.com/top250'
          
          req=requests.get(url,headers=headers)
          
          html=req.text
          #print(req.text)
          
          soup=BeautifulSoup(html,'lxml')
          print(soup.h1)
          print(soup.a)

          執行結果:

          <h1>豆瓣電影 Top 250</h1>  
          <a class="nav-login" href="https://accounts.douban.com/passport/login?source=movie" rel="nofollow">登錄/注冊</a>

          以上,就直接提取到標簽h1和a 的內容了,之所以只有一個,因為只提取第一個匹配到的內容。

          Attributes:

          屬性,一個tag可能有很多個屬性, . tag的屬性的操作方法與字典相同。

          如上:ol class="grid_view" 的屬性, 標簽名為ol,屬性為class,屬性值為:grid_view

          import requests
          from bs4 import BeautifulSoup
          
          headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/65.0.3325.162 Safari/537.36'}
          url='https://movie.douban.com/top250'
          
          req=requests.get(url,headers=headers)
          
          html=req.text
          #print(req.text)
          
          soup=BeautifulSoup(html,'lxml')
          #獲取標簽div所有屬性,得到的是一個字典
          print(soup.div.attrs)
          #獲取標簽ol屬性為class的值
          print(soup.ol['class'])

          執行結果:

          {'id': 'db-global-nav', 'class': ['global-nav']} 
          ['grid_view']

          因為是字典屬性,所以tag的屬性可以被添加,刪除或修改。不過,對于修改刪除的操作,不是我們的主要用途,有需要的自行參考官方文檔。

          (2)NavigableString

          直譯為:可以遍歷的字符串,通過名稱可知,得到字符串。

          標簽內非屬性字符串,格式:soup.\<tag>.string, NavigableString可以跨越多個層次。

          如,得到了標簽的內容,要想獲取標簽內部的文字,用 .string 即可。

          上面代碼改為:

          print(soup.h1.string)

          執行結果:

          豆瓣電影 Top 250

          (3)BeautifulSoup

          BeautifulSoup 對象表示的是一個文檔的全部內容.大部分時候,可以把它當作 Tag 對象,是一個特殊的 Tag,我們可以分別獲取它的類型,名稱。

          print(soup.name)

          執行結果:

          [document]

          (4)Comment

          注釋及特殊字符串,Tag , NavigableString , BeautifulSoup 幾乎覆蓋了html和xml中的所有內容,但是還有一些特殊對象.容易讓人擔心的內容是文檔的注釋部分:

          from bs4 import BeautifulSoup
          
          markup="<b><!--Hey, buddy. Want to buy a used parser?--></b>"
          soup=BeautifulSoup(markup)
          comment=soup.b.string
          print(type(comment))
          print(comment)

          執行結果:

          <class 'bs4.element.Comment'>
          Hey, buddy. Want to buy a used parser?

          四、遍歷文檔樹

          HTML基本格式:<>…</>構成了所屬關系,遍歷形成了標簽的樹形結構。

          所以有時候不能做到一步就得到想要的元素,需要先選中一個元素再以它為基準再選擇它的子節點,父節點,兄弟節點等。

          (1)子節點和子孫節點

          子節點屬性:.contents .children

          .content

          tag 的 .content 屬性可以將tag的子節點以列表的方式輸出

          import requests
          from bs4 import BeautifulSoup
          
          headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/65.0.3325.162 Safari/537.36'}
          url='https://movie.douban.com/top250'
          
          req=requests.get(url,headers=headers)
          
          html=req.text
          #print(req.text)
          
          soup=BeautifulSoup(html,'lxml')
          print(soup.ol.contents)

          執行結果:

          ['\n', <li>
          <div class="item">
          <div class="pic">
          <em class="">1</em>
          <a href="https://movie.douban.com/subject/1292052/">
          <img alt="肖申克的救贖" class="" src="https://img9.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg" width="100"/>
          </a>
          </div> 
          <div class="info">
          ...

          輸出方式為列表,所以可以用列表索引來獲取它的某一個元素。

          print(soup.ol.contents[1])

          .children

          返回的不是一個 list,不過我們可以通過遍歷獲取所有子節點。

          print(soup.ol.children)

          執行結果:

          <list_iterator object at 0x7fbf14fbc4c0>

          打印輸出 .children ,可以發現它是一個 list 生成器對象,所以需要遍歷一下獲取內容。

          for child in soup.ol.children:
              print(child)

          輸入內容和.content差不多。


          子孫節點.descendants

          如果要獲得所有的子孫節點的話,可以調用descendants屬性,返回結果還是生成器,所以需要遍歷一下輸出可以看見span節點

          print(soup.ol.descendants)
          #print(soup.ol.children)
          for child in soup.ol.descendants:
              print(child)

          descendants會遞歸查詢所有子節點,得到所有的子孫節點。

          (2)父節點和祖父節點

          獲取父節點.parent

          print(soup.ol.parent)

          獲取所有祖先節點,同理需要遍歷獲取。

          for parent in soup.ol.parents:
              print(parent)

          (3)兄弟節點

          獲取兄弟節點:.next_sibling .previous_sibling

          next_sibling和previous_sibling分別獲取節點的下一個和上一個兄弟元素。

          print(soup.li.next_sibling)
          print(soup.li.previous_sibling)

          如果節點不存在,則返回 None,實際中通常是字符串或空白,因為空白或者換行也可以被視作一個節點,所以得到的結果可能是空白或者換行。


          全部兄弟節點:next_siblings previous_siblings

          分別返回后面和前面的兄弟節點,同理,所有節點需要遍歷獲得。

          print(soup.li.next_siblings)
          print(soup.li.previous_siblings)
          
          for sibling in soup.li.next_siblings:
              print(sibling)
          for previous in soup.li.previous_siblings:
              print(previous)


          (4)回退和前進節點

          前后節點:.next_element .previous_element

          與 .next_sibling .previous_sibling 不同,它并不是針對于兄弟節點,而是在所有節點,不分層次

          比如 head 節點為

          <head><title>The Dormouse's story</title></head>

          那么它的下一個節點便是 title,它是不分層次關系的。

          所有前后節點:.next_elements .previous_elements

          同理,返回的是迭代器,需要遍歷獲得。

          五、搜索文檔樹

          eautiful Soup定義了很多搜索方法,主要用的2個方法:find() 和 find_all()

          (1)find_all

          語法:find_all(name, attrs, recursive, text, **kwargs)

          name:

          我們可以根據節點名來查詢元素。name可以是:字符串、正則表達式、列表、True、方法

          print(soup.find_all('a'))

          因為是Tag類型,我們可以進行嵌套查詢.

          for a in soup.find_all('a'):
              print(a.find_all('span'))
              print(a.string)

          attrs

          除了根據節點名查詢的話,同樣的也可以通過屬性來查詢。

          print(soup.find_all(attrs={'id': 'link1'}))
          print(soup.find_all(attrs={'name': 'Dormouse'}))

          常用的屬性比如class,我們可以直接傳入class這個參數。在這里需要注意的是class是Python的保留字,所以在class的后面加上下劃線。

          print(soup.find_all(class_="title"))

          執行結果:

          <span class="title">肖申克的救贖</span>, <span class="title"> / The Shawshank Redemption</span>, <span class="title">霸王別姬</span>, <span class="title">阿甘正傳</span>

          (2)find

          除了find_all( )方法,還有find( )方法,前者返回的是多個元素,以列表形式返回,后綴是返回一個元素。即第一個元素。

          find( )與find_all( )的使用方法相同。

          find_parents() 和find_parent():前者返回所有祖先節點,后者返回直接父節點。

          find_next_siblings()和find_next_sibling():前者返回后面的所有兄弟節點,后者返回后面第一個兄弟節點。

          find_previous_siblings和find_previous_sibling():前者返回前面的所有兄弟節點,后者返回前面第一個兄弟節點。

          六、CSS選擇器

          Beautiful Soup還提供了另一種選擇器,即CSS選擇器。

          soup.select(),返回類型是 list。


          同樣可以用 標簽名、類名、 id 名、組合、屬性查找。

          (1)soup.select()

          獲取title標簽節點
          print(soup.select('title'))
          
          獲取class為title的節點
          print(soup.select('.title'))
          
          獲取li標簽下的a節點
          print(soup.select('li a'))
          
          查找時還可以加入屬性元素,屬性需要用中括號括起來,
          注意屬性和標簽屬于同一節點,所以中間不能加空格,否則會無法匹配到
          print soup.select('a[href="http://example.com/elsie"]')

          (2)嵌套選擇

          同樣可以使用嵌套查詢

          for ul in soup.select('ul'):
              print(ul.select('li'))

          (3)獲取屬性

          for ul in soup.select('ul'):
              print(ul['id'])
              print(ul.attrs['id'])

          (4)獲取文本

          for li in soup.select('li'):
              print('String:', li.string)
              print('get text:', li.get_text())


          七、獲取豆瓣電影排行首頁影片信息

          通過以上的方法,現在獲取豆瓣電影排行首頁的排名、電影名、導演演員、年份類型。

          從頁面分析,所有影片信息,在class標簽值為grid_view的里面。

          所以第一步獲取所有grid_view里面所有li標簽的值,返回的是一個列表。

          list=soup.find(class_='grid_view').find_all('li')

          排序,在列表每個元素中,獲取em標簽值,為排序,只取字符串。

          find('em').string

          電影名稱,獲取第一個title值

          find(class_='title').string

          導演和年代信息,在標簽p當中,獲取的是text文本格式。由于中間有空格,還有br換行符,所以最后還需要replace替換掉。

          item.find('p').text.replace(' ','')

          最終代碼為:

          url='https://movie.douban.com/top250'
          
          req=requests.get(url,headers=headers)
          
          html=req.text
          #print(req.text)
          soup=BeautifulSoup(html,'lxml')
          
          list=soup.find(class_='grid_view').find_all('li')
          
          for item in list:
              item_num=item.find('em').string
              item_name=item.find(class_='title').string
              item_act=item.find('p').text.replace(' ','')
              print("排名:"+item_num,"\n電影名稱:"+item_name,item_act)

          執行結果:

          排名:1 
          電影名稱:肖申克的救贖 
          導演:弗蘭克·德拉邦特FrankDarabont   主演:蒂姆·羅賓斯TimRobbins/...
          1994 / 美國 / 犯罪劇情
          
          排名:2 
          電影名稱:霸王別姬 
          導演:陳凱歌KaigeChen   主演:張國榮LeslieCheung/張豐毅FengyiZha...
          1993 / 中國大陸中國香港 / 劇情愛情同性
          
          排名:3 
          電影名稱:阿甘正傳 
          導演:羅伯特·澤米吉斯RobertZemeckis   主演:湯姆·漢克斯TomHanks/...
          1994 / 美國 / 劇情愛情
          
          排名:4 
          電影名稱:泰坦尼克號 
          導演:詹姆斯·卡梅隆JamesCameron   主演:萊昂納多·迪卡普里奧Leonardo...
          1997 / 美國墨西哥澳大利亞加拿大 / 劇情愛情災難
          
          排名:5 
          電影名稱:這個殺手不太冷 
          導演:呂克·貝松LucBesson   主演:讓·雷諾JeanReno/娜塔莉·波特曼...
          1994 / 法國美國 / 劇情動作犯罪
          
          排名:6 
          電影名稱:美麗人生 
          導演:羅伯托·貝尼尼RobertoBenigni   主演:羅伯托·貝尼尼RobertoBeni...
          1997 / 意大利 / 劇情喜劇愛情戰爭
          
          排名:7 
          電影名稱:千與千尋 
          導演:宮崎駿HayaoMiyazaki   主演:柊瑠美RumiH?ragi/入野自由Miy...
          2001 / 日本 / 劇情動畫奇幻
          
          排名:8 
          電影名稱:辛德勒的名單 
          導演:史蒂文·斯皮爾伯格StevenSpielberg   主演:連姆·尼森LiamNeeson...
          1993 / 美國 / 劇情歷史戰爭
          
          排名:9 
          電影名稱:盜夢空間 
          導演:克里斯托弗·諾蘭ChristopherNolan   主演:萊昂納多·迪卡普里奧Le...
          2010 / 美國英國 / 劇情科幻懸疑冒險
          
          排名:10 
          電影名稱:星際穿越 
          導演:克里斯托弗·諾蘭ChristopherNolan   主演:馬修·麥康納MatthewMc...
          2014 / 美國英國加拿大 / 劇情科幻冒險
          
          排名:11 
          電影名稱:忠犬八公的故事 
          導演:萊塞·霍爾斯道姆LasseHallstr?m   主演:理查·基爾RichardGer...
          2009 / 美國英國 / 劇情
          
          排名:12 
          電影名稱:楚門的世界 
          導演:彼得·威爾PeterWeir   主演:金·凱瑞JimCarrey/勞拉·琳妮Lau...
          1998 / 美國 / 劇情科幻
          
          排名:13 
          電影名稱:海上鋼琴師 
          導演:朱塞佩·托納多雷GiuseppeTornatore   主演:蒂姆·羅斯TimRoth/...
          1998 / 意大利 / 劇情音樂
          
          排名:14 
          電影名稱:三傻大鬧寶萊塢 
          導演:拉庫馬·希拉尼RajkumarHirani   主演:阿米爾·汗AamirKhan/卡...
          2009 / 印度 / 劇情喜劇愛情歌舞
          
          排名:15 
          電影名稱:機器人總動員 
          導演:安德魯·斯坦頓AndrewStanton   主演:本·貝爾特BenBurtt/艾麗...
          2008 / 美國 / 科幻動畫冒險
          
          排名:16 
          電影名稱:放牛班的春天 
          導演:克里斯托夫·巴拉蒂ChristopheBarratier   主演:讓-巴蒂斯特·莫尼...
          2004 / 法國瑞士德國 / 劇情喜劇音樂
          
          排名:17 
          電影名稱:無間道 
          導演:劉偉強/麥兆輝   主演:劉德華/梁朝偉/黃秋生
          2002 / 中國香港 / 劇情犯罪驚悚
          
          排名:18 
          電影名稱:瘋狂動物城 
          導演:拜倫·霍華德ByronHoward/瑞奇·摩爾RichMoore   主演:金妮弗·...
          2016 / 美國 / 喜劇動畫冒險
          
          排名:19 
          電影名稱:大話西游之大圣娶親 
          導演:劉鎮偉JeffreyLau   主演:周星馳StephenChow/吳孟達ManTatNg...
          1995 / 中國香港中國大陸 / 喜劇愛情奇幻古裝
          
          排名:20 
          電影名稱:熔爐 
          導演:黃東赫Dong-hyukHwang   主演:孔侑YooGong/鄭有美Yu-miJung/...
          2011 / 韓國 / 劇情
          
          排名:21 
          電影名稱:控方證人 
          導演:比利·懷爾德BillyWilder   主演:泰隆·鮑華TyronePower/瑪琳·...
          1957 / 美國 / 劇情犯罪懸疑
          
          排名:22 
          電影名稱:教父 
          導演:弗朗西斯·福特·科波拉FrancisFordCoppola   主演:馬龍·白蘭度M...
          1972 / 美國 / 劇情犯罪
          
          排名:23 
          電影名稱:當幸福來敲門 
          導演:加布里爾·穆奇諾GabrieleMuccino   主演:威爾·史密斯WillSmith...
          2006 / 美國 / 劇情傳記家庭
          
          排名:24 
          電影名稱:觸不可及 
          導演:奧利維·那卡什OlivierNakache/艾力克·托蘭達EricToledano   主...
          2011 / 法國 / 劇情喜劇
          
          排名:25 
          電影名稱:怦然心動 
          導演:羅伯·萊納RobReiner   主演:瑪德琳·卡羅爾MadelineCarroll/卡...
          2010 / 美國 / 劇情喜劇愛情


          八、小結

          推薦使用lxml解析庫,必要時選擇html.parser。相對于正則表達式,Beautiful Soup更加簡單,但是網上有些推薦正則表達式,理由是精確。

          具體用哪個,還是根據環境選擇吧,一起使用都可以。

          .NET的SelectPdf Html到Pdf轉換器-社區版是.NET的SelectPdf庫中提供的功能強大的html到pdf轉換器的免費版本。
          轉換器提供了許多強大的選項(將任何網頁轉換為pdf,將任何html字符串轉換為pdf,html5 / css3 / javascript支持,頁眉和頁腳支持等),唯一的限制是它最多可以生成pdf文檔。5頁長。
          .NET的免費HTML至Pdf轉換器–社區版功能:最多生成5頁pdf文檔,將任何網頁轉換為pdf,將任何原始html字符串轉換為pdf,設置pdf頁面設置(頁面大小,頁面方向,頁面邊距) ,在轉換過程中調整內容大小以適合pdf頁面,設置pdf文檔屬性,設置pdf查看器首選項,設置pdf安全性(密碼,權限),設置轉換延遲和網頁導航超時,自定義頁眉和頁腳,在頁眉中支持html和頁腳,自動和手動分頁符,在每個頁面上重復html表頭,支持@media類型屏幕和打印,支持內部和外部鏈接,基于html元素自動生成書簽,支持HTTP標頭,支持HTTP cookie,支持需要身份驗證的網頁,支持代理服務器,啟用/禁用javascript,修改顏色空間,多線程支持,HTML5 / CSS3支持,Web字體支持等等。


          代碼實現

          1、nuget 引用

          Install-Package Select.HtmlToPdf

          2、方法

          • using SelectPdf;using System.Collections.Specialized;using System.IO;using System.Web;
            namespace BQoolCommon.Helpers.File{ public class WebToPdf { public WebToPdf() { //SelectPdf.GlobalProperties.LicenseKey="your-license-key"; }
            /// <summary> /// 將 Html 轉成 PDF,並儲存成檔案 /// </summary> /// <param name="html">html</param> /// <param name="fileName">絕對路徑</param> public void SaveToFileByHtml(string html, string fileName) { var doc=SetPdfDocument(html); doc.Save(fileName); }
            /// <summary> /// 傳入 Url 轉成 PDF,並儲存成檔案 /// </summary> /// <param name="url">url</param> /// <param name="fileName">絕對路徑</param> /// <param name="httpCookies">Cookies</param> public void SaveToFileByUrl(string url, string fileName, NameValueCollection httpCookies) { var doc=SetPdfDocument(url, httpCookies); doc.Save(fileName); }
            /// <summary> /// 將 Html 轉成 PDF,並輸出成 byte[] 格式 /// </summary> /// <param name="html">html</param> /// <returns></returns> public byte[] GetFileByteByHtml(string html) { var doc=SetPdfDocument(html); return doc.Save(); }
            /// <summary> /// 傳入 Url 轉成 PDF,並輸出成 byte[] 格式 /// </summary> /// <param name="url">url</param> /// <param name="httpCookies">Cookies</param> /// <returns></returns> public byte[] GetFileByteByUrl(string url, NameValueCollection httpCookies) { var doc=SetPdfDocument(url, httpCookies); return doc.Save(); }
            /// <summary> /// 將 Html 轉成 PDF,並輸出成 Stream 格式 /// </summary> /// <param name="html">html</param> /// <returns></returns> public Stream GetFileStreamByHtml(string html) { var doc=SetPdfDocument(html); var pdfStream=new MemoryStream();
            doc.Save(pdfStream); pdfStream.Position=0;
            return pdfStream; }
            /// <summary> /// 傳入 Url 轉成 PDF,並輸出成 Stream 格式 /// </summary> /// <param name="html">html</param> /// <returns></returns> public Stream GetFileStreamByUrl(string url, NameValueCollection httpCookies) { var doc=SetPdfDocument(url, httpCookies); var pdfStream=new MemoryStream();
            doc.Save(pdfStream); pdfStream.Position=0;
            return pdfStream; }
            private PdfDocument SetPdfDocument(string html) { var converter=new HtmlToPdf();
            converter.Options.WebPageWidth=1200; html=HttpUtility.HtmlDecode(html);
            return converter.ConvertHtmlString(html); }
            private PdfDocument SetPdfDocument(string url, NameValueCollection httpCookies) { var converter=new HtmlToPdf(); converter.Options.WebPageWidth=1200;
            if (httpCookies != && httpCookies.Count !=0) { converter.Options.HttpCookies.Add(httpCookies); }
            return converter.ConvertUrl(url); }
            }}

            3、調用

            • /// <summary> /// 下載pdf /// </summary> public void Downpdf(string data) { var stream=new BQoolCommon.Helpers.File.WebToPdf().GetFileStreamByHtml(Gethtml(data)); Response.Clear(); //二進制流數據(如常見的文件下載) Response.ContentType="application/octet-stream"; //通知瀏覽器下載文件而不是打開 Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode("Profit and Loss Statement.pdf", System.Text.Encoding.UTF8)); var bytes=StreamToBytes(stream); Response.BinaryWrite(bytes); Response.Flush(); stream.Close(); stream.Dispose();
              Response.End(); }

              那么如何獲取指定頁面的html 呢 傳入對應的model 獲得指定動態的html

              • private string Gethtml(string data) { string str="";
                str=this.ControllerContext.RenderViewToString("ProfitDetails", data);
                return str; }
                • using BQoolCommon.Helpers.Format;using Newtonsoft.Json;using OrdersManager.Models.ViewModel.Report;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Web;using System.Web.Mvc;
                  namespace OrdersManager.Web.Infrastructure{ public static class HelperExtensions { public static string RenderViewToString(this ControllerContext context, string viewName, string data) { if (string.IsOrEmpty(viewName)) viewName=context.RouteData.GetRequiredString("action");
                  context.Controller.ViewData.Model=JsonConvert.DeserializeObject<ProfitDetailsmodel>(StringTools.Base64Decode(StringTools.Base64Decode(data)));
                  using (var sw=new StringWriter()) { ViewEngineResult viewResult=ViewEngines.Engines.FindPartialView(context, viewName); var viewContext=new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw); try { viewResult.View.Render(viewContext, sw); } catch (Exception ex) { throw; }
                  return sw.GetStringBuilder().ToString(); } } }}

                  參考文檔

                  https://www.nuget.org/packages/Select.HtmlToPdf/

          難度:入門級

          python版本:3.7

          主要收獲:爬蟲經驗+100;python經驗+100

          主要會用到python和爬蟲技術,入門級項目,偏簡單,適合新人練手,看這個之前最好是對python和爬蟲有一些了解

          需求

          需求名稱:采集《python進階》教程

          網頁:https://docs.pythontab.com/interpy/

          需求:采集網頁上的所有進階內容,并整理成文檔

          采集具體的進階教程內容即可

          需求分析

          我們看下需求,需要采集的東西并不是很多,我們先打開網頁看一下

          看下目錄,數據量不是很多

          大致數了一下就幾十個頁面,這很少了

          對應下需求,根據經驗,列下我們需要解決的一些問題

          單頁面抓取問題

          多頁面url獲取問題

          整理成文檔

          單頁面抓取問題

          這個問題其實就是看下抓取頁面的請求構造

          我們先找下源代碼中是否有包含我們所需要的數據

          在頁面上找個稍微特殊的詞

          比如說 “小清新”

          鍵盤按下ctrl+U查看下源代碼

          在按下ctrl+F,查找“小清新”

          可以看到,源碼中就直接有我們所需要的數據,那么可以判斷,這八成就是一個get請求

          如果沒有反爬,那就比較簡單了

          直接構建一個最簡單的get請求試一下

          import requests

          r=requests.get('https://docs.pythontab.com/interpy/')

          print(r.text)

          print(r)

          運行一下,打印輸出的是有我們需要的數據(由于太多就不貼了),完美!

          多頁面url獲取問題

          我們可以看到所需要采集的頁面幾十個,并不是很多,就需求目標而言,我們其實是可以一個個的復制下來,但是這樣沒有技術范兒,而且如果說我們采集的頁面很多呢,幾百幾千,甚至幾十萬,手動復制的效率實在過于低下

          我們打開網頁

          可以看到有個Next按鈕

          這里就有下一頁的url

          我們跳到最后一頁,就會發現Next沒有了

          那么我們是不是就可以通過這種方式來拿到各個頁面的url

          我們一直去提Next按鈕獲取下一頁的url,直到最后一頁,沒有Next,判斷結束

          整理成文檔

          本來想將抓取到的內容(去標簽)保存成txt的,然后在轉成pdf格式,好看一些

          不過由于保存的內容沒有格式,轉換后并不好看,所以決定不去標簽,直接存成html文件

          然后在轉換成pdf

          這里有個在線的將html轉成pdf,還是滿好用的:https://www.aconvert.com/cn/ebook/

          代碼實現

          邏輯理清了,代碼實現就比較簡單了

          直接上下代碼

          import requests

          from lxml import etree

          from urllib import parse

          def get_html(url):

          """網頁采集數據,并保存到文件中

          Args:

          url (str): 待采集的url

          Returns:

          str: 下一頁的url

          """

          r=requests.get(url)

          html=etree.HTML(r.text)

          content=html.xpath('//div[@role="main"]')

          content0=etree.tostring(content[0])

          # print(content0)

          with open("python進階教程.html","ab+") as f:

          f.write(content0)

          _next=html.xpath("//a[contains(text(),'Next ?')]/@href")

          if not _next:

          return ''

          nexturl=parse.urljoin(url,_next[0])

          print(nexturl)

          return nexturl

          url='https://docs.pythontab.com/interpy/'

          while 1:

          url=get_html(url)

          if not url:

          break

          運行代碼會在當前目錄生成一個python進階教程.html文件

          打開看一眼

          還是可以的,不過我這里把它轉換成更通用的pdf類型

          html轉換成pdf

          先打開在線轉換的網頁:https://www.aconvert.com/cn/ebook/

          選擇html文件

          選擇轉換的目標格式

          點擊轉換

          下載文件

          打開pdf看一下

          格式還是很完美的!

          注:

          其實python有個pdfkit庫,可以將一個html轉換成pdf,有興趣的朋友可以嘗試下

          關注我獲取更多內容


          主站蜘蛛池模板: 久久精品一区二区国产| 日本精品一区二区三区在线视频一 | 在线成人综合色一区| 中文无码精品一区二区三区 | 国产高清一区二区三区四区| 亚洲无圣光一区二区| 久久精品亚洲一区二区| 色欲综合一区二区三区| 免费无码一区二区三区| 亚洲电影一区二区| 国产精品一区二区三区免费| 成人一区专区在线观看| 精品国产高清自在线一区二区三区| 国产精品无码一区二区三区在| 全国精品一区二区在线观看| 中文字幕在线观看一区| 亚洲av无码一区二区三区不卡| 亚洲一区二区三区亚瑟| 丰满爆乳无码一区二区三区| 麻豆一区二区三区蜜桃免费| 三上悠亚精品一区二区久久| 久久精品亚洲一区二区三区浴池| 成人免费视频一区| 成人区精品人妻一区二区不卡| 久久无码人妻一区二区三区午夜| 日韩福利视频一区| 精品国产一区二区三区免费| 国产香蕉一区二区三区在线视频 | 国产一区二区三区美女| 插我一区二区在线观看| 99精品国产一区二区三区2021| 亚洲一区欧洲一区| 国产福利一区二区三区在线观看 | 无码人妻一区二区三区免费视频| 丝袜无码一区二区三区| 亚洲av无码一区二区三区网站| 亚洲AV无码片一区二区三区| 天堂Aⅴ无码一区二区三区| 精品国产一区二区三区久久久狼| 日本精品一区二区三区四区| 精品无码人妻一区二区三区|