『壹』 如何用python開發一個簡單的Webkit瀏覽器
在這篇教程中,我們會用 Python 的 PyQt 框架編寫一個簡單的 web 瀏覽器。關於 PyQt ,你可能已經有所耳聞了,它是 Qt 框架下的一系列 Python 組件,而 Qt(發音類似「cute」)是用來開發GUI的 C++ 框架。嚴格來講, Qt 也可用於開發不帶圖形界面的程序,但是開發用戶界面應該是 Qt 框架最為廣泛的應用了。Qt 的主要優勢是可以開發跨平台的圖形界面程序,基於 Qt 的應用能夠藉助於各平台的原生性在不同類的設備上運行,而無須修改任何代碼庫。
Qt 附帶了webkit的介面,你可以直接使用 PyQt 來開發一個基於 webkit 的瀏覽器。
我們本次教程所開發的瀏覽器可以完成如下功能:
載入用戶輸入的url
顯示在渲染頁面過程中發起的所有請求
允許用戶在頁面中執行自定義的 JavaScript 腳本
牛刀小試
讓我們從最簡單的 PyQt 的 Webkit 用例開始吧:輸入 url,打開窗口並在窗口中載入頁面。
這個例子十分短小,連import語句和空行在內也只有 13 行代碼。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
import sys
from PyQt4.QtWebKit import QWebView
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl
app = QApplication(sys.argv)
browser = QWebView()
browser.load(QUrl(sys.argv[1]))
browser.show()
app.exec_()
當你通過命令行將 url 傳給腳本時,程序會載入 url 並且在窗口中顯示載入完成的頁面。
現在,看似你已經有一個「命令行瀏覽器」啦!至少比 python 的 requests 模塊強多了,甚至比Lynx還略高一籌,因為我們的瀏覽器還可以載入 JavaScript 腳本呢。但是目前為止還沒有跟 Lynx 拉開差距,因為在啟用瀏覽器的時候只能通過命令行傳入 url。那麼,必然需要通過某種方式把需要載入的 url 傳入瀏覽器。沒錯,就是地址欄!
添加地址欄
其實地址欄的實現非常簡單,我們只需要在窗口頂端加一個輸入框就夠了。用戶在文本框中輸入 url 之後,瀏覽器就會載入這個地址。下面,我們將用到 QLineEdit 控制項來實現輸入框。鑒於我們的瀏覽器現在有地址欄和瀏覽器顯示框兩部分,因此還要給我們的應用增加一個網格布局。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import sys
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl
from PyQt4.QtWebKit import QWebView
from PyQt4.QtGui import QGridLayout, QLineEdit, QWidget
class UrlInput(QLineEdit):
def __init__(self, browser):
super(UrlInput, self).__init__()
self.browser = browser
# add event listener on "enter" pressed
self.returnPressed.connect(self._return_pressed)
def _return_pressed(self):
url = QUrl(self.text())
# load url into browser frame
browser.load(url)
if __name__ == "__main__":
app = QApplication(sys.argv)
# create grid layout
grid = QGridLayout()
browser = QWebView()
url_input = UrlInput(browser)
# url_input at row 1 column 0 of our grid
grid.addWidget(url_input, 1, 0)
# browser frame at row 2 column 0 of our grid
grid.addWidget(browser, 2, 0)
# main app window
main_frame = QWidget()
main_frame.setLayout(grid)
main_frame.show()
# close app when user closes window
sys.exit(app.exec_())
到這里,我們已經有一個瀏覽器的雛形啦!看上去和當年的 Google Chrome 還有幾分相像呢,畢竟兩者採用了相同的渲染引擎。現在,你可以在輸入框中輸入 url ,程序便會將地址傳入瀏覽器,接著渲染出所有的 HTML 頁面和 JavaScript 腳本並展示出來。
添加開發工具
一個瀏覽器最有趣也最重要的部分是什麼?當然是各種各樣的開發工具了!一個沒有開發者控制台的瀏覽器怎麼能算是瀏覽器呢?所以,我們的 Python 瀏覽器當然也要有一些開發者工具才行。
現在,我們就來添加一些類似於 Chrome 的開發者工具中 「Network」 標簽的功能吧!這個功能就是簡單地追蹤瀏覽器引擎在載入頁面的時候所執行的所有請求。在瀏覽器主頁面的下方,我們將通過一個表來顯示這些請求。簡單起見,我們只會記錄登錄的 url、返回的狀態碼和響應的內容類型。
首先我們要通過 QTableWidget 組件創建一個表格,表頭包括需要存儲的欄位名稱,表格可以根據每次新插入的記錄來自動調整大小。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class RequestsTable(QTableWidget):
header = ["url", "status", "content-type"]
def __init__(self):
super(RequestsTable, self).__init__()
self.setColumnCount(3)
self.setHorizontalHeaderLabels(self.header)
header = self.horizontalHeader()
header.setStretchLastSection(True)
header.setResizeMode(QHeaderView.ResizeToContents)
def update(self, data):
last_row = self.rowCount()
next_row = last_row + 1
self.setRowCount(next_row)
for col, dat in enumerate(data, 0):
if not dat:
continue
self.setItem(last_row, col, QTableWidgetItem(dat))
想要追蹤所有請求的話,我們還需要對 PyQt 的內部構件有更深入的了解。了解到,Qt 提供了一個 NetworkAccessManager類作為 API 介面,通過調用它可以監控應用載入頁面時所執行的請求。我們需要自己編寫一個繼承自 NetworkAccessManager 的子類,添加必要的事件監聽器,然後使用我們自己編寫的 manager 來通知 webkit 視圖執行相應的請求。
首先我們需要以 NetworkAccessManager 為基類創建我們自己的網路訪問管理器。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Manager(QNetworkAccessManager):
def __init__(self, table):
QNetworkAccessManager.__init__(self)
# add event listener on "load finished" event
self.finished.connect(self._finished)
self.table = table
def _finished(self, reply):
"""Update table with headers, status code and url.
"""
headers = reply.rawHeaderPairs()
headers = {str(k):str(v) for k,v in headers}
content_type = headers.get("Content-Type")
url = reply.url().toString()
# getting status is bit of a pain
status = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
status, ok = status.toInt()
self.table.update([url, str(status), content_type])
在這里需要提醒大家的是, Qt 的某些實現並不像想像中那麼簡單明了,比如說從響應中獲取狀態碼就十分繁瑣。首先,你得把請求對象的類屬性作為參數傳入 response 的方法.attribute()中,.attribute()方法的返回值是 QVariant 類型而非 int 類型。接著,需要調用內置函數.toInt()將其轉換成一個包含兩個元素的元組,最終得到響應的狀態碼。
現在,我們終於有了一個記錄請求的表和一個監控網路的 manager,接下來只要把他們聚攏起來就可以了。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if __name__ == "__main__":
app = QApplication(sys.argv)
grid = QGridLayout()
browser = QWebView()
url_input = UrlInput(browser)
requests_table = RequestsTable()
manager = Manager(requests_table)
# to tell browser to use network access manager
# you need to create instance of QWebPage
page = QWebPage()
page.setNetworkAccessManager(manager)
browser.setPage(page)
grid.addWidget(url_input, 1, 0)
grid.addWidget(browser, 2, 0)
grid.addWidget(requests_table, 3, 0)
main_frame = QWidget()
main_frame.setLayout(grid)
main_frame.show()
sys.exit(app.exec_())
現在,運行瀏覽器程序,在地址欄鍵入 url,就可以看到在主頁面下方的記錄表中記錄下的所有請求。
如果你有興趣的話,還可以為瀏覽器添加很多新的功能:
通過content-type添加篩選功能
添加記錄表的排序功能
添加計時器
高亮顯示出錯的請求(比如說把錯誤信息置為紅色)
顯示出更為具體的請求內容,比如說完整的頭信息、響應內容、請求方法等。
增加一個重復發送請求並載入出來的選項。比如說用戶可以點擊在記錄表中的請求來重試請求。
其實還有太多的功能可以繼續完善和改進,你可以一一嘗試一下,這會是一個非常有趣而且收獲良多的學習過程。但是如果想把這些功能都說完,估計都能寫一本書了。所以限於篇幅,本文就不一一介紹了,感興趣的朋友可以參考其他書籍和網上教程。
增加解析自定義 JavaScript 腳本的功能
我們終於迎來最後一個功能了!就是解析在頁面中包含的 JavaScript 腳本。
基於我們之前已經打下的基礎,要完成這個功能非常簡單。我們只需要在添加一個 QLineEdit 組件,把它和頁面聯系起來,然後調用evaulateJavaScript方法就可以了。
Python
1
2
3
4
5
6
7
8
9
class JavaScriptEvaluator(QLineEdit):
def __init__(self, page):
super(JavaScriptEvaluator, self).__init__()
self.page = page
self.returnPressed.connect(self._return_pressed)
def _return_pressed(self):
frame = self.page.currentFrame()
result = frame.evaluateJavaScript(self.text())
下面是這個功能的示例。看,我們的開發者工具已經整裝待發了!
Python
1
2
3
4
5
6
7
8
9
10
11
if __name__ == "__main__":
# ...
# ...
page = QWebPage()
# ...
js_eval = JavaScriptEvaluator(page)
grid.addWidget(url_input, 1, 0)
grid.addWidget(browser, 2, 0)
grid.addWidget(requests_table, 3, 0)
grid.addWidget(js_eval, 4, 0)
現在唯一缺少的就是在頁面中不能執行 Python 腳本。你可以開發自己的瀏覽器,提供對 JavaScript 和 Python 的支持,這樣其他開發者就可以針對你的瀏覽器開發應用了。
後退、前進和其他頁面操作
我們在前面已經使用了 QWebPage 對象來開發瀏覽器,當然作為一個合格的瀏覽器,我們也需要為終端用戶提供一些重要功能。Qt 的網頁對象支持很多不同操作,我們可以把它們全都添加到瀏覽器中。
現在我們可以先嘗試著添加「後退」、「前進」和「刷新」這幾個操作。你可以在界面上添加這些操作按鈕,簡單起見,這里只加一個文本框來執行這些動作。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ActionInputBox(QLineEdit):
def __init__(self, page):
super(ActionInputBox, self).__init__()
self.page = page
self.returnPressed.connect(self._return_pressed)
def _return_pressed(self):
frame = self.page.currentFrame()
action_string = str(self.text()).lower()
if action_string == "b":
self.page.triggerAction(QWebPage.Back)
elif action_string == "f":
self.page.triggerAction(QWebPage.Forward)
elif action_string == "s":
self.page.triggerAction(QWebPage.Stop)
和之前一樣,我們要創建一個 ActionInputBox 的實例,把參數傳入頁面對象並把輸入框對象添加到頁面中。
For reference here』s code for final result 示例代碼看這里
[1]: Graphical User Interface,圖形用戶界面,又稱圖形用戶介面,是指採用圖形方式顯示的計算機操作用戶界面。
[2]: WebKit是一個開源的瀏覽器引擎,與之相對應的引擎有 Gecko(Mozilla Firefox 等使用)和 Trident(也稱 MSHTML ,IE 使用)。
『貳』 python 怎樣設置代理訪問http請求
有幾種方法。一種是設置環境變數http_proxy,它會自動訪問這個。 另外一種是你使用urllib2的時候,在參數里加上代理。還有一個是urllib上指定。
比如
import urllib
urllib.urlopen(某網站,proxyes={'http:':"某代理IP地址:代理的埠"})
使用QT時,它的瀏覽器設置代理要在瀏覽器初始化參數里指定。
『叄』 如何用python分析從瀏覽器到伺服器的HTTP GET請求的內容。
用response = requests.get(url),對response.content的內容進行正則分析或者用bs4等模塊進行分析即可
『肆』 Python的 request 庫,請求頭是什麼
就是headers,照抄瀏覽器F12里那一堆就行,如下圖,請求標頭下面所有內容都是。
『伍』 如何用Python寫一個http post請求
HTTP 協議規定 POST 提交的數據必須放在消息主體(entity-body)中,但協議並沒有規定數據必須使用什麼編碼方式。常見的四種編碼方式如下:
1、application/x-www-form-urlencoded
這應該是最常見的 POST 提交數據的方式了。瀏覽器的原生 form 表單,如果不設置 enctype 屬性,那麼最終就會以 application/x-www-form-urlencoded 方式提交數據。請求類似於下面這樣(無關的請求頭在本文中都省略掉了):
POST HTTP/1.1 Content-Type:
application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
2、multipart/form-data
這又是一個常見的 POST 數據提交的方式。我們使用表單上傳文件時,必須讓 form 的 enctyped 等於這個值,下面是示例
POST HTTP/1.1
Content-Type:multipart/form-data; boundary=----
------
Content-Disposition: form-data; name="text"
title
------
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
--------
3、application/json
application/json 這個 Content-Type 作為響應頭大家肯定不陌生。實際上,現在越來越多的人把它作為請求頭,用來告訴服務端消息主體是序列化後的 JSON 字元串。由於 JSON 規范的流行,除了低版本 IE 之外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會遇上什麼麻煩。
4、text/xml
它是一種使用 HTTP 作為傳輸協議,XML 作為編碼方式的遠程調用規范。
那麼Python在調用外部http請求時,post請求怎麼傳請求體呢?說實話樓主只實踐過【1、application/x-www-form-urlencoded】【2、multipart/form-data 】和【3、application/json】
一、application/x-www-form-urlencoded
import urllib
url = ""
body_value = {"package": "com.tencent.lian","version_code": "66" }
body_value = urllib.urlencode(body_value)
request = urllib2.Request(url, body_value)
request.add_header(keys, headers[keys])
result = urllib2.urlopen(request ).read()
二、multipart/form-data
需要利用python的poster模塊,安裝poster:pip install poster
代碼:
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
url = ""
body_value = {"package": "com.tencent.lian","version_code": "66" }
register_openers()
datagen, re_headers = multipart_encode(body_value)
request = urllib2.Request(url, datagen, re_headers)
# 如果有請求頭數據,則添加請求頭
request .add_header(keys, headers[keys])
result = urllib2.urlopen(request ).read()
二、application/json
import json
url = ""
body_value = {"package": "com.tencent.lian","version_code": "66" }
register_openers()
body_value = json.JSONEncoder().encode(body_value)
request = urllib2.Request(url, body_value)
request .add_header(keys, headers[keys])
result = urllib2.urlopen(request ).read()
『陸』 python編寫介面,請求url應該如何確定
1、是一個介面
2、程序需要運行後才能訪問,可以部署到伺服器上,程序一旦運行是守護進程,只要不關閉程序一直會運行
3、請求的url根據'/xxx'來確定,請求的類型 methods=['get']
『柒』 求給源代碼!python可以通過函數實現上網用瀏覽器搜索並返回指定內容嗎急急急急急急急急急!!!
可以使用網路漢語來做。
urlencode是漢字在url中的形式,它是漢字的utf-8編碼各位元組的十六進制值(以%為前綴)
例如「中國」編碼後是%E4%B8%AD%E5%9B%BD
網路漢語可以直接以get方法來起調,只需要用參數wd傳入要查的字或詞即可。
對於字和詞,網路漢語返回不同的頁面,因此,使用一個if來做分支,分別處理不同的頁面。
因為要求不使用下載的包,那麼,就直接使用python內置的requests來做請求,撿出拼音用re簡單處理一下就好。
這是沒有處理多音字的,如果要多音字返回所有讀音,那麼第一個分支里寫法要改一改,判斷讀音段落結束才返回讀音列表,每個讀音【re.findall】的結果要添加到讀音列表
『捌』 python request請求返回內容和瀏覽器返回的不同
這個有可能是因為你爬取的網站有反爬機制,識別你是程序訪問的不返回網頁內容。
『玖』 如何用Python爬蟲抓取網頁內容
首先,你要安裝requests和BeautifulSoup4,然後執行如下代碼.
importrequests
frombs4importBeautifulSoup
iurl='http://news.sina.com.cn/c/nd/2017-08-03/doc-ifyitapp0128744.shtml'
res=requests.get(iurl)
res.encoding='utf-8'
#print(len(res.text))
soup=BeautifulSoup(res.text,'html.parser')
#標題
H1=soup.select('#artibodyTitle')[0].text
#來源
time_source=soup.select('.time-source')[0].text
#來源
origin=soup.select('#artibodyp')[0].text.strip()
#原標題
oriTitle=soup.select('#artibodyp')[1].text.strip()
#內容
raw_content=soup.select('#artibodyp')[2:19]
content=[]
forparagraphinraw_content:
content.append(paragraph.text.strip())
'@'.join(content)
#責任編輯
ae=soup.select('.article-editor')[0].text
這樣就可以了