整合營銷服務商

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

          免費咨詢熱線:

          最近又火了一個Web自動化工具,python大神都在用

          開源精選》是我們分享Github、Gitee等開源社區中優質項目的欄目,包括技術、學習、實用與各種有趣的內容。本期推薦的是一個開源基于 python 的 Web 自動化操作集成工具——DrissionPage。

          requests 做數據采集面對要登錄的網站時,要分析數據包、JS 源碼,構造復雜的請求,往往還要應付驗證碼、JS 混淆、簽名參數等反爬手段,門檻較高。若數據是由 JS 計算生成的,還須重現計算過程,體驗不好,開發效率不高。

          使用 selenium,可以很大程度上繞過這些坑,但 selenium 效率不高。因此,這個庫將 seleniumrequests 合而為一,不同須要時切換相應模式,并提供一種人性化的使用方法,提高開發和運行效率。

          除了合并兩者,本庫還以網頁為單位封裝了常用功能,簡化了 selenium 的操作和語句,在用于網頁自動化操作時,減少考慮細節,專注功能實現,使用更方便。一切從簡,盡量提供簡單直接的使用方法,對新手更友好。


          特性

          • 代碼高度集成,以簡潔的代碼為第一追求。
          • 頁面對象可在 seleniumrequests 模式間任意切換,保留登錄狀態。
          • 極簡單但強大的元素定位語法,支持鏈式操作,代碼極其簡潔。
          • 兩種模式提供一致的 API,使用體驗一致。
          • 人性化設計,集成眾多實用功能,大大降低開發工作量

          亮點功能

          • 每次運行程序可以反復使用已經打開的瀏覽器。如手動設置網頁到某個狀態,再用程序接管,或手動處理登錄,再用程序爬內容。無須每次運行從頭啟動瀏覽器,超級方便
          • 使用 ini 文件保存常用配置,自動調用,也提供便捷的設置 API,遠離繁雜的配置項
          • 極致簡明的定位語法,支持直接按文本定位元素,支持直接獲取前后兄弟元素和父元素等
          • 強大的下載工具,操作瀏覽器時也能享受快捷可靠的下載功能
          • 下載工具支持多種方式處理文件名沖突、自動創建目標路徑、斷鏈重試等
          • 訪問網址帶自動重試功能,可設置間隔和超時時間
          • 訪問網頁能自動識別編碼,無須手動設置
          • 鏈接參數默認自動生成Host和Referer屬性
          • 可以隨時直接隱藏或顯示瀏覽器進程窗口,非 headless 或最小化
          • 可自動下載合適版本的 chromedriver,免去麻煩的配置
          • d 模式查找元素內置等待,可任意設置全局等待時間或單次查找等待時間
          • 點擊元素集成 js 點擊方式,一個參數即可切換點擊方式
          • 點擊支持失敗重試,可用于保證點擊成功、判讀網頁遮罩層是否消失等
          • 輸入文本能自動判斷是否成功并重試,避免某些情況下輸入或清空失效的情況發生
          • d 模式下支持全功能的 xpath,可直接獲取元素的某個屬性,selenium 原生無此功能
          • 支持直接獲取shadow-root,和普通元素一樣操作其下的元素
          • 支持直接獲取after和before偽元素的內容
          • 可以在元素下直接使用 > 以 css selector 方式獲取當前元素直接子元素。原生不支持這種寫法
          • 可簡單地使用 lxml 來解析 d 模式的頁面或元素,爬取復雜頁面數據時速度大幅提高
          • 輸出的數據均已轉碼及處理基本排版,減少重復勞動
          • 可方便地與 selenium 或 requests 原生代碼對接,便于項目遷移
          • 使用 POM 模式封裝,可直接用于測試,便于擴展
          • d 模式配置可同時兼容debugger_address和其它參數,原生不能兼容


          結構圖

          如圖所示,Drission對象負責鏈接的創建、共享登錄狀態等工作,類似 seleniumdriver 的概念。MixPage對象負責對獲取到的頁面進行解析、操作。DriverElementSessionElement則是從頁面對象中獲取到的元素對象。負責對元素進行解析和操作。

          簡單演示

          與 selenium 代碼對比

          跳轉到第一個標簽頁

          # 使用 selenium:
          driver.switch_to.window(driver.window_handles[0])
          
          # 使用 DrissionPage:
          page.to_tab(0)

          按文本選擇下拉列表

          # 使用 selenium:
          from selenium.webdriver.support.select import Select
          
          select_element = Select(element)
          select_element.select_by_visible_text('text')
          
          # 使用 DrissionPage:
          element.select('text')

          拖拽一個元素

          # 使用 selenium:
          ActionChains(driver).drag_and_drop(ele1, ele2).perform()
          
          # 使用 DrissionPage:
          ele1.drag_to(ele2)

          與 requests 代碼對比

          獲取元素內容

          url = 'https://baike.baidu.com/item/python'
          
          # 使用 requests:
          from lxml import etree
          
          headers = {
              'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36'}
          response = requests.get(url, headers=headers)
          html = etree.HTML(response.text)
          element = html.xpath('//h1')[0]
          title = element.text
          
          # 使用 DrissionPage:
          page = MixPage('s')
          page.get(url)
          title = page('tag:h1').text

          下載文件

          url = 'https://www.baidu.com/img/flexible/logo/pc/result.png'
          save_path = r'C:\download'
          
          # 使用 requests:
          r = requests.get(url)
          with open(f'{save_path}\\img.png', 'wb') as fd:
             for chunk in r.iter_content():
                 fd.write(chunk)
                  
          # 使用 DrissionPage:
          page.download(url, save_path, 'img')  # 支持重命名,處理文件名沖突,自動創建目標文件夾

          爬取新冠排行榜

          網址:https://www.outbreak.my/zh/world,此示例爬取全球新冠情況排行榜。該網站是純 html 頁面,特別適合 s 模式爬取和解析。

          from DrissionPage import MixPage
          
          # 用 s 模式創建頁面對象
          page = MixPage('s')  
          # 訪問數據網頁
          page.get('https://www.outbreak.my/zh/world')  
          
          # 獲取表頭元素
          thead = page('tag:thead')  
          # 獲取表頭列,跳過其中的隱藏的列
          title = thead.eles('tag:th@@-style:display: none;')  
          data = [th.text for th in title]
          
          print(data)  # 打印表頭
          
          # 獲取內容表格元素
          tbody = page('tag:tbody')  
          # 獲取表格所有行
          rows = tbody.eles('tag:tr')  
          
          for row in rows: 
              # 獲取當前行所有列
              cols = row.eles('tag:td')  
              # 生成當前行數據列表(跳過其中沒用的幾列)
              data = [td.text for k, td in enumerate(cols) if k not in (2, 4, 6)]
              
              print(data)  # 打印行數據

          輸出:

          ['總 (205)', '累積確診', '死亡', '治愈', '現有確診', '死亡率', '恢復率']
          ['美國', '55252823', '845745', '41467660', '12,939,418', '1.53%', '75.05%']
          ['印度', '34838804', '481080', '34266363', '91,361', '1.38%', '98.36%']
          ['巴西', '22277239', '619024', '21567845', '90,370', '2.78%', '96.82%']
          ['英國', '12748050', '148421', '10271706', '2,327,923', '1.16%', '80.57%']
          ['俄羅斯', '10499982', '308860', '9463919', '727,203', '2.94%', '90.13%']
          ['法國', '9740600', '123552', '8037752', '1,579,296', '1.27%', '82.52%']
          ......
          

          登錄 gitee 網站

          網址:https://gitee.com/login,此示例演示使用控制瀏覽器的方式自動登錄 gitee 網站。

          from DrissionPage import MixPage
          
          # 用 d 模式創建頁面對象(默認模式)
          page = MixPage()
          # 跳轉到登錄頁面
          page.get('https://gitee.com/login')
          
          # 定位到賬號文本框并輸入賬號
          page.ele('#user_login').input('你的賬號')
          # 定位到密碼文本框并輸入密碼
          page.ele('#user_password').input('你的密碼')
          # 點擊登錄按鈕
          page.ele('@value=登 錄').click()


          —END—

          開源協議:BSD-3-Clause

          開源地址: https://gitee.com/g1879/DrissionPage

          析網站,梳理獲取的思路:

          查看到直接是有圖片的鏈接的,但是這只是當前的頁面,繼續往下翻,發現有些圖片是懶加載的,并沒有圖片的鏈接。對于未瀏覽到的內容,其提供的圖片是空白的圖片鏈接。

          但是,他們都提供了圖片詳情頁的鏈接。

          所以這里有兩個思路,一個是解決懶加載的問題,另外一個是獲取圖片詳情頁,進入圖片詳情頁中再下載圖片。這里我們選擇第二種,至此,思路就清晰了。

          整理思路:

          請求要爬取的頁面→獲取該頁面所有的圖片詳情頁鏈接→請求詳情頁,獲取具體的圖片鏈接→請求圖片具體鏈接,獲取圖片二進制內容,保存到本地

          利用代碼實現:

          from curl_cffi import requests
          from lxml import etree
          
          url = "https://pixabay.com/zh/illustrations/search/%e8%87%aa%e7%84%b6/"
          
          headers = {
              'User-Agent':'Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',    
          }
          # 第一次請求,獲取該頁面所有的圖片詳情頁鏈接
          req = requests.get(url,headers=headers,impersonate='chrome')
          
          html_tree = etree.HTML(req.text)
          
          pic_srclist = html_tree.xpath('//a[@class="link--WHWzm"]/@href')
          
          # print(pic_srclist)
          print(req.status_code)
          i = 0
          for pic_src in pic_srclist:
              i = i + 1
              picpage_url = "https://pixabay.com"+pic_src
              print('正在獲取',i)
              #第二次請求,獲取圖片詳情頁中的圖片鏈接
              temp_req = requests.get(url = picpage_url,headers=headers,impersonate='chrome')
              temp_tree = etree.HTML(temp_req.text)
              pic_url = temp_tree.xpath('//div[@class="container--3Mtk4"]//img/@src')[0]
              pic_alt = temp_tree.xpath('//div[@class="container--3Mtk4"]//img/@alt')[0]
              pic_name = pic_url.split('/')[-1]
          
              # 第三次請求,獲取圖片具體鏈接
              temp_req = requests.get(url = pic_url,headers=headers,impersonate='chrome')
              with open(pic_name,'wb') as f:
                  f.write(temp_req.content)
              print(pic_name,'獲取完成!')

          終端輸出:

          爬取結果:

          還在為看小說受到廣告影響而煩惱嗎?不如利用起時間,跟著本文一起入門python爬蟲,實現小說自由!

          介紹

          本項目的全部內容包括:

          1.搜索功能實現

          2.根據所選小說爬取全部章節列表

          3.在線閱讀所選章節

          正文

          預配置

          在一般的無反爬蟲情形下,python請求網頁信息的請求頭較為簡單,只寫User-Agent項即可,可在檢查中任意請求的請求頭中查看

          配置代碼如下:

          def __init__(self):
          self._headers={
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
          "Chrome/98.0.4758.102 Safari/537.36 Edg/98.0.1108.55"
          }
          self._search_url = 'https://www.xbiquwx.la/modules/article/search.php?searchkey='
          self._book_url = 'https://www.xbiquwx.la'
          self.session = requests.session()

          上段代碼中使用了session會話機制,可有效提升python的requests訪問網站速度

          搜索

          在小說網站搜索萬相之王,檢查網絡元素

          發現其請求的url如上圖中所示,其中的searchkey即為搜索文字的url編碼

          分析網頁源碼可知,我們所需的書名和鏈接均位于class屬性值為grid的table標簽中,使用xpath語法即可提取標簽內容和標簽屬性

          綜上,這一部分輸入書名搜索返回結果的代碼如下:

          def search(self, name:str):
          if name:
          response = self.session.get(
          url = self._search_url + name,
          headers = self._headers
          )
          html = etree.HTML(response.content.decode())
          self.bookID = html.xpath('//table[@class="grid"]/tr/td[@class="odd"]/a/@href')
          bookNameTag = html.xpath('//table[@class="grid"]/tr/td[@class="odd"]/a')
          self.bookName = [item.text for item in bookNameTag]
          return self.bookName

          獲取章節列表

          打開任意一本書籍,檢查加載書籍章節時的網絡訪問情況

          可以發現請求的地址就是我們上一步中得到的書籍url,進一步證實了想法

          在這里我們發現所有章節名稱和url信息全部位于網頁源碼的dd標簽中,同上,利用xpath語法提取

          這一部分獲取章節名字的代碼如下:

          def chapLists(self, index:int):
          response = self.session.get(
          url = self._book_url + self.bookID[index],
          headers = self._headers
          )
          self.index = index
          html = etree.HTML(response.content.decode())
          self.chapUrls = html.xpath('//div[@class="box_con"]/div[@id="list"]//a/@href')
          self.chapTitles = html.xpath('//div[@class="box_con"]/div[@id="list"]//a/@title')
          self.chapUrls.reverse()
          self.chapTitles.reverse()
          return self.chapTitles

          在線閱讀

          我們打開任意一章小說,審查網絡元素

          同樣可以發現所請求的網站就是上一步中得到的章節地址

          在網頁源碼中我們發現小說正文部分位于id屬性為content的div標簽中,編寫代碼提取正文內容:

          def read(self, index:int):
          response = self.session.get(
          url = self._book_url + self.bookID[self.index] + self.chapUrls[index],
          headers = self._headers
          )
          code = response.apparent_encoding
          html = etree.HTML(response.content.decode())
          articleRaw = html.xpath('//div[@class="content_read"]//div[@id="content"]')
          a0 = etree.tostring(articleRaw[0],encoding=code).decode(code)
          a2 = a0[32:-29]
          article = "<h1>"+self.chapTitles[index]+"</h1>"+'<font size="5"><br />'+a2+"</font>"
          return article

          到此,我們已經掌握了整個小說閱讀的來龍去脈

          總結

          整個網絡小說在線閱讀類封裝如下:

          import requests
          from lxml import etree
          class bqCrawler():
          def __init__(self):
          self._headers={
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
          "Chrome/98.0.4758.102 Safari/537.36 Edg/98.0.1108.55"
          }
          self._search_url = 'https://www.xbiquwx.la/modules/article/search.php?searchkey='
          self._book_url = 'https://www.xbiquwx.la'
          self.session = requests.session()
          def search(self, name:str):
          if name:
          response = self.session.get(
          url = self._search_url + name,
          headers = self._headers
          )
          html = etree.HTML(response.content.decode())
          self.bookID = html.xpath('//table[@class="grid"]/tr/td[@class="odd"]/a/@href')
          bookNameTag = html.xpath('//table[@class="grid"]/tr/td[@class="odd"]/a')
          self.bookName = [item.text for item in bookNameTag]
          return self.bookName
          def chapLists(self, index:int):
          response = self.session.get(
          url = self._book_url + self.bookID[index],
          headers = self._headers
          )
          self.index = index
          html = etree.HTML(response.content.decode())
          self.chapUrls = html.xpath('//div[@class="box_con"]/div[@id="list"]//a/@href')
          self.chapTitles = html.xpath('//div[@class="box_con"]/div[@id="list"]//a/@title')
          self.chapUrls.reverse()
          self.chapTitles.reverse()
          return self.chapTitles
          def read(self, index:int):
          response = self.session.get(
          url = self._book_url + self.bookID[self.index] + self.chapUrls[index],
          headers = self._headers
          )
          code = response.apparent_encoding
          html = etree.HTML(response.content.decode())
          articleRaw = html.xpath('//div[@class="content_read"]//div[@id="content"]')
          a0 = etree.tostring(articleRaw[0],encoding=code).decode(code)
          a2 = a0[32:-29]
          article = "<h1>"+self.chapTitles[index]+"</h1>"+'<font size="5"><br />'+a2+"</font>"
          return article

          在此基礎上我們稍作修飾,用PyQt5為其開發一個可視化面板,最終效果如圖:


          主站蜘蛛池模板: 免费无码一区二区| 国产精品区AV一区二区| 色窝窝无码一区二区三区成人网站| 色婷婷AV一区二区三区浪潮| 蜜臀AV一区二区| 国产91一区二区在线播放不卡| 中文字幕精品一区| 精品国产一区二区三区av片| 中文字幕精品无码一区二区三区| 亚洲欧美日韩国产精品一区| 国精品无码A区一区二区| 武侠古典一区二区三区中文| 国产一区中文字幕| 日韩a无吗一区二区三区| 国产精品分类视频分类一区| 久久精品无码一区二区无码| 精品国产一区二区三区2021| 免费一区二区三区在线视频| 立川理惠在线播放一区| 日本精品无码一区二区三区久久久| 亚洲国产精品第一区二区| 丝袜无码一区二区三区| 久久久国产精品一区二区18禁| 伊人激情AV一区二区三区| 日本免费电影一区二区 | 国产午夜精品片一区二区三区| 亚洲一区二区久久| 国偷自产视频一区二区久| 国产伦精品一区二区三区视频小说| 国产婷婷色一区二区三区深爱网 | 消息称老熟妇乱视频一区二区| 免费无码VA一区二区三区| AA区一区二区三无码精片| 天美传媒一区二区三区| 国产亚洲综合一区二区三区| 国产综合精品一区二区| 久久一区二区三区99| 亚洲av成人一区二区三区在线播放| 日韩国产免费一区二区三区| 免费在线视频一区| 国产精品一区二区久久精品涩爱|