欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python+PyQt5實(shí)現(xiàn)美劇爬蟲可視工具的方法

 更新時(shí)間:2019年04月25日 10:03:55   作者:豐寸  
這篇文章主要介紹了Python+PyQt5實(shí)現(xiàn)美劇爬蟲可視工具的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

美劇《權(quán)力的游戲》終于要開播最后一季了,作為馬丁老爺子的忠實(shí)粉絲,為了能夠看得懂第八季復(fù)雜龐大的劇情架構(gòu),本人想著將前幾季再穩(wěn)固一下,所以就上美劇天堂下載來看,可是每次都上去下載太麻煩了,于是干脆自己寫個(gè)爬蟲爬下來得了。

話不多說,先上圖片。

本人才疏學(xué)淺,就寫了個(gè)簡(jiǎn)單的可視化軟件,關(guān)鍵是功能實(shí)現(xiàn)就行了嘛。

實(shí)現(xiàn)語言:Python ,版本 3.7.1

實(shí)現(xiàn)思路:首先運(yùn)用 Python 工具爬取到數(shù)據(jù)再實(shí)現(xiàn)圖形化軟件。

由于這里只是實(shí)現(xiàn)簡(jiǎn)單的爬取數(shù)據(jù),并沒有牽扯到 cookie 之類的敏感信息,也沒有設(shè)置代理,所以在選擇 Python 庫上并沒有引入 Selenium 或者更高級(jí)的 Scrapy 框架,只是拿到數(shù)據(jù)就可以了,沒必要那么麻煩。

所以選擇了 urllib 這個(gè)庫,在 Python 2.X 中應(yīng)該是 urllib 和 urllib2 同時(shí)引入,由于本人選用的版本的 Python 3.X ,在 Python 3.X 中上面兩個(gè)庫已經(jīng)被合并為 urllib 一個(gè)庫,語法上有些不同,但語言這種東西都是大同小異的嘛。

先貼代碼,緩和一下尷尬的氣氛。

import urllib.request
from urllib import parse
from lxml import etree
import ssl
from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QTextEdit, QVBoxLayout, QPushButton, QMessageBox
import sys

# 取消代理驗(yàn)證
ssl._create_default_https_context = ssl._create_unverified_context

class TextEditMeiJu(QWidget):
 def __init__(self, parent=None):
  super(TextEditMeiJu, self).__init__(parent)
  # 定義窗口頭部信息
  self.setWindowTitle('美劇天堂')
  # 定義窗口的初始大小
  self.resize(500, 600)
  # 創(chuàng)建單行文本框
  self.textLineEdit = QLineEdit()
  # 創(chuàng)建一個(gè)按鈕
  self.btnButton = QPushButton('確定')
  # 創(chuàng)建多行文本框
  self.textEdit = QTextEdit()
  # 實(shí)例化垂直布局
  layout = QVBoxLayout()
  # 相關(guān)控件添加到垂直布局中
  layout.addWidget(self.textLineEdit)
  layout.addWidget(self.btnButton)
  layout.addWidget(self.textEdit)
  # 設(shè)置布局
  self.setLayout(layout)
  # 將按鈕的點(diǎn)擊信號(hào)與相關(guān)的槽函數(shù)進(jìn)行綁定,點(diǎn)擊即觸發(fā)
  self.btnButton.clicked.connect(self.buttonClick)

 # 點(diǎn)擊確認(rèn)按鈕
 def buttonClick(self):
  # 爬取開始前提示一下
  start = QMessageBox.information(
   self, '提示', '是否開始爬取《' + self.textLineEdit.text() + "》",
   QMessageBox.Ok | QMessageBox.No, QMessageBox.Ok
  )
  # 確定爬取
  if start == QMessageBox.Ok:
   self.page = 1
   self.loadSearchPage(self.textLineEdit.text(), self.page)
  # 取消爬取
  else:
   pass

 # 加載輸入美劇名稱后的頁面
 def loadSearchPage(self, name, page):
  # 將文本轉(zhuǎn)為 gb2312 編碼格式
  name = parse.quote(name.encode('gb2312'))
  # 請(qǐng)求發(fā)送的 url 地址
  url = "https://www.meijutt.com/search/index.asp?page=" + str(page) + "&searchword=" + name + "&searchtype=-1"
  # 請(qǐng)求報(bào)頭
  headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"}
  # 發(fā)送請(qǐng)求
  request = urllib.request.Request(url, headers=headers)
  # 獲取請(qǐng)求的 html 文檔
  html = urllib.request.urlopen(request).read()
  # 對(duì) html 文檔進(jìn)行解析
  text = etree.HTML(html)
  # xpath 獲取想要的信息
  pageTotal = text.xpath('//div[@class="page"]/span[1]/text()')
  # 判斷搜索內(nèi)容是否有結(jié)果
  if pageTotal:
   self.loadDetailPage(pageTotal, text, headers)
  # 搜索內(nèi)容無結(jié)果
  else:
   self.infoSearchNull()

 # 加載點(diǎn)擊搜索頁面點(diǎn)擊的本季頁面
 def loadDetailPage(self, pageTotal, text, headers):
  # 取出搜索的結(jié)果一共多少頁
  pageTotal = pageTotal[0].split('/')[1].rstrip("頁")
  # 獲取每一季的內(nèi)容(劇名和鏈接)
  node_list = text.xpath('//a[@class="B font_14"]')
  items = {}
  items['name'] = self.textLineEdit.text()
  # 循環(huán)獲取每一季的內(nèi)容
  for node in node_list:
   # 獲取信息
   title = node.xpath('@title')[0]
   link = node.xpath('@href')[0]
   items["title"] = title
   # 通過獲取的單季鏈接跳轉(zhuǎn)到本季的詳情頁面
   requestDetail = urllib.request.Request("https://www.meijutt.com" + link, headers=headers)
   htmlDetail = urllib.request.urlopen(requestDetail).read()
   textDetail = etree.HTML(htmlDetail)
   node_listDetail = textDetail.xpath('//div[@class="tabs-list current-tab"]//strong//a/@href')
   self.writeDetailPage(items, node_listDetail)
  # 爬取完畢提示
  if self.page == int(pageTotal):
   self.infoSearchDone()
  else:
   self.infoSearchContinue(pageTotal)

 # 將數(shù)據(jù)顯示到圖形界面
 def writeDetailPage(self, items, node_listDetail):
  for index, nodeLink in enumerate(node_listDetail):
   items["link"] = nodeLink
   # 寫入圖形界面
   self.textEdit.append(
    "<div>"
     "<font color='black' size='3'>" + items['name'] + "</font>" + "\n"
     "<font color='red' size='3'>" + items['title'] + "</font>" + "\n"
     "<font color='orange' size='3'>第" + str(index + 1) + "集</font>" + "\n"
     "<font color='green' size='3'>下載鏈接:</font>" + "\n"
     "<font color='blue' size='3'>" + items['link'] + "</font>"
     "<p></p>"
    "</div>"
   )

 # 搜索不到結(jié)果的提示信息
 def infoSearchNull(self):
  QMessageBox.information(
   self, '提示', '搜索結(jié)果不存在,請(qǐng)重新輸入搜索內(nèi)容',
   QMessageBox.Ok, QMessageBox.Ok
  )

 # 爬取數(shù)據(jù)完畢的提示信息
 def infoSearchDone(self):
  QMessageBox.information(
   self, '提示', '爬取《' + self.textLineEdit.text() + '》完畢',
   QMessageBox.Ok, QMessageBox.Ok
  )

 # 多頁情況下是否繼續(xù)爬取的提示信息
 def infoSearchContinue(self, pageTotal):
  end = QMessageBox.information(
   self, '提示', '爬取第' + str(self.page) + '頁《' + self.textLineEdit.text() + '》完畢,還有' + str(int(pageTotal) - self.page) + '頁,是否繼續(xù)爬取',
   QMessageBox.Ok | QMessageBox.No, QMessageBox.No
  )
  if end == QMessageBox.Ok:
   self.page += 1
   self.loadSearchPage(self.textLineEdit.text(), self.page)
  else:
   pass


if __name__ == '__main__':
 app = QApplication(sys.argv)
 win = TextEditMeiJu()
 win.show()
 sys.exit(app.exec_())

以上是實(shí)現(xiàn)功能的所有代碼,可以運(yùn)行 Python 的小伙伴直接復(fù)制到本地運(yùn)行即可。都說 Python 是做爬蟲最好的工具,寫完之后發(fā)現(xiàn)確實(shí)是這樣。

我們一點(diǎn)點(diǎn)分析代碼:

import urllib.request
from urllib import parse
from lxml import etree
import ssl
from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QTextEdit, QVBoxLayout, QPushButton, QMessageBox, QLabel
import sys

以上為我們引入的所需要的庫,前 4 行是爬取 美劇天堂 官網(wǎng)所需要的庫,后兩個(gè)是實(shí)現(xiàn)圖形化應(yīng)用所需的庫。

我們先來看一下如何爬取網(wǎng)站信息。

由于現(xiàn)在 美劇天堂 使用的是 https 協(xié)議,進(jìn)入頁面需要代理驗(yàn)證,為了不必要的麻煩,我們干脆取消代理驗(yàn)證,所以用到了 ssl 模塊。

然后我們就可以正大光明的進(jìn)入網(wǎng)站了:

令人遺憾的是 url 鏈接為https://www.meijutt.com/search/index.asp,顯然沒有為我們提供任何有用的信息,當(dāng)我們刷新頁面時(shí),如下圖:

當(dāng)我們手動(dòng)輸入 ulr 鏈接https://www.meijutt.com/search/index.asp進(jìn)行搜索時(shí):

很明顯了,當(dāng)我們?cè)谑醉撦斎胂肟吹拿绖〔⑺阉鲿r(shí)網(wǎng)站將我們的請(qǐng)求表單信息隱藏了,并沒有給到 url 鏈接里,但是本人可不想每次都從首頁進(jìn)行搜索再提交表單獲取信息,很不爽,還好本人發(fā)現(xiàn)了一個(gè)更好的方法。如下圖:

在頁面頂部有一個(gè)頁面跳轉(zhuǎn)的按鈕,我們可以選擇跳轉(zhuǎn)的頁碼,當(dāng)選擇跳轉(zhuǎn)頁碼后,頁面變成了如下:

url 鏈接已經(jīng)改變了:https://www.meijutt.com/search/index.asp?page=&searchword=%C8%A8%C1%A6%B5%C4%D3%CE%CF%B7&searchtype=-1

我們?cè)賹?page 中動(dòng)態(tài)添加為page=1,頁面效果不變。

經(jīng)過搜索多個(gè)不同的美劇的多次驗(yàn)證發(fā)現(xiàn)只有 page 和 searchword 這兩個(gè)字段是改變的,其中 page 字段默認(rèn)為 1 ,而其本人搜索了許多季數(shù)很長(zhǎng)的美劇,比如《老友記》、《生活大爆炸》、《邪惡力量》,這些美劇也就一頁,但仍有更長(zhǎng)的美劇,比如《辛普森一家》是兩頁,《法律與秩序》是兩頁,這就要求我們對(duì)頁數(shù)進(jìn)行控制,但是需要特別注意的是如果隨意搜索內(nèi)容,比如在搜索框只搜索了一個(gè) ”i“,整整搜出了219頁,這要扒下來需要很長(zhǎng)的時(shí)間,所以就需要對(duì)其搜索的頁數(shù)進(jìn)行控制。

我們?cè)賮砜匆幌?searchword 字段,將 searchword 字段解碼轉(zhuǎn)成漢字:

沒錯(cuò),正是我們想要的,萬里長(zhǎng)征終于實(shí)現(xiàn)了第一步。

# 加載輸入美劇名稱后的頁面
def loadSearchPage(self, name, page):
 # 將文本轉(zhuǎn)為 gb2312 編碼格式
 name = parse.quote(name.encode('gb2312'))
 # 請(qǐng)求發(fā)送的 url 地址
 url = "https://www.meijutt.com/search/index.asp?page=" + str(page) + "&searchword=" + name + "&searchtype=-1"
 # 請(qǐng)求報(bào)頭
 headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"}
 # 發(fā)送請(qǐng)求
 request = urllib.request.Request(url, headers=headers)
 # 獲取請(qǐng)求的 html 文檔
 html = urllib.request.urlopen(request).read()
 # 對(duì) html 文檔進(jìn)行解析
 text = etree.HTML(html)
 # xpath 獲取想要的信息
 pageTotal = text.xpath('//div[@class="page"]/span[1]/text()')
 # 判斷搜索內(nèi)容是否有結(jié)果
 if pageTotal:
  self.loadDetailPage(pageTotal, text, headers)
 # 搜索內(nèi)容無結(jié)果
 else:
  self.infoSearchNull()

接下來我們只需要將輸入的美劇名轉(zhuǎn)化成 url 編碼格式就可以了。如上代碼,通過 urllib 庫對(duì)搜索的網(wǎng)站進(jìn)行操作。

其中我們還需要做判斷,搜索結(jié)果是否存在,比如我們搜索 行尸跑肉,結(jié)果不存在。

當(dāng)搜索結(jié)果存在時(shí):

我們通過谷歌的 xpath 插件對(duì)頁面內(nèi)的 dom 進(jìn)行搜索,發(fā)現(xiàn)我們要選取的 class 類名。

我們根據(jù)獲取到的頁數(shù),找到所有頁面里我們要搜索的信息:

# 加載點(diǎn)擊搜索頁面點(diǎn)擊的本季頁面
def loadDetailPage(self, pageTotal, text, headers):
 # 取出搜索的結(jié)果一共多少頁
 pageTotal = pageTotal[0].split('/')[1].rstrip("頁")
 # 獲取每一季的內(nèi)容(劇名和鏈接)
 node_list = text.xpath('//a[@class="B font_14"]')
 items = {}
 items['name'] = self.textLineEdit.text()
 # 循環(huán)獲取每一季的內(nèi)容
 for node in node_list:
  # 獲取信息
  title = node.xpath('@title')[0]
  link = node.xpath('@href')[0]
  items["title"] = title
  # 通過獲取的單季鏈接跳轉(zhuǎn)到本季的詳情頁面
  requestDetail = urllib.request.Request("https://www.meijutt.com" + link, headers=headers)
  htmlDetail = urllib.request.urlopen(requestDetail).read()
  textDetail = etree.HTML(htmlDetail)
  node_listDetail = textDetail.xpath('//div[@class="tabs-list current-tab"]//strong//a/@href')
  self.writeDetailPage(items, node_listDetail)
 # 爬取完畢提示
 if self.page == int(pageTotal):
  self.infoSearchDone()
 else:
  self.infoSearchContinue(pageTotal)

我們根據(jù)獲取到的鏈接,再次通過 urllib 庫進(jìn)行頁面訪問,即我們手動(dòng)點(diǎn)擊進(jìn)入其中的一個(gè)頁面,比如 權(quán)利的游戲第一季,再次通過 xpath 獲取到我們所需要的下載鏈接:

至此我們就將所有我們搜索到的 權(quán)力的游戲 的下載鏈接拿到手了,接下來就是寫圖形界面了。

本人選用了 PyQt5 這個(gè)框架,它內(nèi)置了 QT 的操作語法,對(duì)于本人這種小白用起來也很友好。至于如何使用本人也都在代碼上添加了注釋,在這兒做一下簡(jiǎn)單的說明,就不過多解釋了。

from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QTextEdit, QVBoxLayout, QPushButton, QMessageBox, QLabel
import sys

將獲取的信息寫入搜索結(jié)果內(nèi):

# 將數(shù)據(jù)顯示到圖形界面
def writeDetailPage(self, items, node_listDetail):
 for index, nodeLink in enumerate(node_listDetail):
  items["link"] = nodeLink
  # 寫入圖形界面
  self.textEdit.append(
   "<div>"
    "<font color='black' size='3'>" + items['name'] + "</font>" + "\n"
    "<font color='red' size='3'>" + items['title'] + "</font>" + "\n"
    "<font color='orange' size='3'>第" + str(index + 1) + "集</font>" + "\n"
    "<font color='green' size='3'>下載鏈接:</font>" + "\n"
    "<font color='blue' size='3'>" + items['link'] + "</font>"
    "<p></p>"
   "</div>"
  )

因?yàn)榭赡苡卸囗撉闆r,所以我們得做一次判斷,提示一下剩余多少頁,可以選擇繼續(xù)爬取或停止,做到人性化交互。

# 搜索不到結(jié)果的提示信息
def infoSearchNull(self):
 QMessageBox.information(
  self, '提示', '搜索結(jié)果不存在,請(qǐng)重新輸入搜索內(nèi)容',
  QMessageBox.Ok, QMessageBox.Ok
 )

# 爬取數(shù)據(jù)完畢的提示信息
def infoSearchDone(self):
 QMessageBox.information(
  self, '提示', '爬取《' + self.textLineEdit.text() + '》完畢',
  QMessageBox.Ok, QMessageBox.Ok
 )

# 多頁情況下是否繼續(xù)爬取的提示信息
def infoSearchContinue(self, pageTotal):
 end = QMessageBox.information(
  self, '提示', '爬取第' + str(self.page) + '頁《' + self.textLineEdit.text() + '》完畢,還有' + str(int(pageTotal) - self.page) + '頁,是否繼續(xù)爬取',
  QMessageBox.Ok | QMessageBox.No, QMessageBox.No
 )
 if end == QMessageBox.Ok:
  self.page += 1
  self.loadSearchPage(self.textLineEdit.text(), self.page)
 else:
  pass

demo 圖形化軟件操作如下:

在搜索框內(nèi)輸入要搜索的美劇名,點(diǎn)擊確認(rèn)。提示一下是否要爬取,點(diǎn)擊 No 不爬取,點(diǎn)擊 OK 爬取。

判斷一下是否存在搜索結(jié)果,比如吧 ”辛普森一家“ 換成了 ”吉普森一家“,搜索內(nèi)容不存在。

如果搜索內(nèi)容存在,在搜索完成第一頁后提示一下是否需要繼續(xù)爬取,點(diǎn)擊 No 表示停止爬取,點(diǎn)擊 OK 表示繼續(xù)爬取。

最后爬取完畢后提示爬取完畢:

由于本人對(duì) Python 了解不深,代碼中有很多不足之處,需要不斷學(xué)習(xí)改進(jìn),代碼中有任何要改進(jìn)的地方請(qǐng)各位大佬批評(píng)指教!

最后本人做了一套包含 Mac 和 windows 版的圖形化美劇天堂抓包程序,只需要在對(duì)應(yīng)電腦上點(diǎn)擊運(yùn)行即可,需要的小伙伴可以在本人的公眾號(hào)后臺(tái)回復(fù)美劇天堂就可以拿到了,注:在 windows 上打包生成的 .exe 軟件第一打開時(shí)被 360 阻止,大家允許操作就可以了,Mac 無此提示。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論