爬蟲
爬蟲
點擊這里還可以去我的博客主頁o
點擊這里還可以去大神的學習筆記o
本頁只是為了方便本人以后復習爬蟲用的筆記markdown
純屬娛樂,如有雷同,打死不認——
- 什么是網絡爬蟲與爬蟲實現原理
- Urllib簡單的爬取網頁
- 編碼問題
- requests庫
- 正則表達式和BeautifulSoup
- selenium
- cookie
- mongoDB
- py生成exe
- 自己的案列
- 網絡爬蟲由 控制節點,爬蟲節點,資源庫構成,而在寫爬蟲中一定注意元組()與列表的區別[],字典{}和集合{}的區別
爬蟲的流程
手動操作
分析頁面數據
1查看源代碼
2查看是否是 a jax異步加載
3解密 (非常熟悉前端,特別是js)
decode 解碼 把其他編碼轉化為unicode decode('utf8')把utf-8轉化為unicode
encode 編碼 把unicod轉化為其他編碼 encode('gbk') 把unicode轉化為gbk
可以這樣理解unicode為中文 gbk為日文 utf-8為英文
轉碼只能轉中文 所以就是 日文轉英文 =就是 日轉中轉英 unicode就是像中間人
所以gbk怎樣轉為utf-8 : decode('gbk').encode('utf8')
在這給自己補充下,我現在是主要用pycharm和vscode和jupytur notebook寫python
pycharm的話,操作簡單,寫起來方便快捷,但是注意虛擬環境,這個可以參考Django.md,而且在pip時簡單,如果錯誤就是原因是連接超時,所以需要自己設定安裝源,
解決方法:
在 pip命令后自己設定收集源(-i +url)
eg:pip install requests -i http://pypi.douban.com/simple --trusted-host pypi.douban.com(通過豆瓣)就ok了
由於自己手殘。把虛擬刪除了,所以重新virtualenv pachong_env還要在pycharm里面選擇已經存在的虛擬和解釋器,選擇是已經存在的,不然重新的又要pycharm自己主動創建一個虛擬環境
vscode的話輕便,需要創建一個文件夾,比如我的就是D:\新建文件夾,為什么在這個文件夾里面能寫python因為已經在vscode里設置了詳情自己百度,而且里面有一個D:\新建文件夾.vscode\setting.josn,這就是關鍵
jupytur notebook 直接打開annocod但是也可以直接打開筆記本通過瀏覽器127.0.0.1:8888也可以
元組是一種序列類型,可以索引,而且可以用,和()定義,當時元組是不可變的列表是可變的
列表是一種常見的數據結構,與元組相比,列表是可變的,len可以獲得列表的長度,列表支持索引和切片,還可以append在末尾追加新的元素和extend在末尾追加新的序列(如元組或列表)方法,還支持pop,insert,remove,
字典是一種常用的數據結構,字典所以不同,使用(key)鍵進行索引,與鍵對應的值是值(value),keys就是鍵和值,字典就是由若干鍵值對構成,並且鍵值都有引號,冒號分開
header={'host':www.adad .com'}
集合的特點是無序而且無重復元素,可以使用set()和大括號{}來初始化集合
s=set(['a','b'])
s={'a','b'}
enumerate是一種操作函數可以返回列表元組的索引和值
for ind ,val in enumerate([10,20,40])
print(ind,val)
...
0 10
1 20
2 40
...
在很長的代碼中很有可能出問題,所以有異常處理機制
try:
print('to do')
a = 10/0
print(a)
except Exception as e:
print(e)
finally:
print('我都執行')
執行的結果為
---
to do
division by zero
我都執行
------
#那怎樣主動拋出一個錯誤
來接着看:
class makeErr(ValueError):
pass
def make_error(a):
n = int(a)
if n==0:
raise makeErr('我是一個錯誤')
return 1/n
make_error(0)
結果為
make_error(0)
File "D:/Python_code/pachong/pachong1.py", line 18, in make_error
raise makeErr('我是一個錯誤')
__main__.makeErr: 我是一個錯誤
爬蟲按照技術和結構分為通用網絡爬蟲,聚焦網絡爬蟲,增量式網絡爬蟲,深層網絡爬蟲等,實際網絡爬蟲通常是幾種的組合體
一般都是由url集合,url隊列,頁面爬取,頁面分析,頁面數據庫,鏈接過濾,內容評價,鏈接評價,想辦法自動填寫表單等
- 我們通過兩種經典爬蟲為例(通用爬蟲和聚焦爬蟲為例)分別記錄他們的實現原理並且通過他們找到共同點
- 通用網絡爬蟲
1獲取初始的url,初始的url地址可以 由用戶人為的指定,也可以由用戶指定的某個或幾個初始的網頁決定
2根據初始的URL爬取頁面並獲得新的URL,將網頁儲蓄在原始的數據庫中,並且在爬取網頁中發現了新的url將已爬取的URL地址存放在一個URL列表中,再去重或者判斷爬取的進程
3爬取新的URL列表里的URL並且有可能再爬取新URL中又再獲得URL再加入列表,以此重復
4滿足爬蟲系統的停止條件后停止爬取 - 聚焦網絡爬蟲
1由於其有目的的爬取,所以對於聚焦爬蟲來說必須增加目標的定義和過濾機制還有下一句URL地址的選取等,所以第一步是做好爬取需求的定義和描述
2獲取初始URL
3根據初始URL爬取並獲得新的URL
4從新的URL過濾掉無用的,對有需要的放入URL列表,再去重和判斷爬取的進程
5從URL列表中,根據搜索算法,確定URL優先級,並確定下一步要爬取的URL地址,在聚焦爬蟲中,確定下一步的URL比較重要
然后又是從下一步的URL讀取新的URL,並重復
6滿足停止條件時停止
- 使用urllib庫爬取網頁的簡單操作
在使用urllib前知道,當你獲取一個URL你使用一個opener。在一般,我們都是使用的默認的opener,也就是urlopen。它是一個特殊的opener,可以理解成opener的一個特殊實例,傳入的參數僅僅是url,data,timeout。
import urllib.request
url='http://www.baidu.com'
print('第一種')
response1=urllib.request.urlopen(url)
print (response1.getcode())
print (len(response1.read()))
結果為
第一種
200
153295
urllib思路也是大概一樣
1首先,爬取一個網頁並讀出來賦給一個變量
2 以寫入的方式打開一個文件,將值寫入文件
3關閉文件
import urllib.request
file = urllib.request.urlopen('http://www.baidu.com')
data=file.read()
fhandle=open('D:/Python_code/pachong/handle/1.html','wb')
fhandle.write(data)
fhandle.close()
之前一直錯因為我寫錯了
fhandle=open('D:D:\Python_code\pachong\handle\1.html','wb')
千萬別復制路徑,可能我的電腦這只原因,斜杠反的 一直錯誤
如果要進行編碼和解碼,比如我們對網址進行編碼
import urllib.request
file = urllib.request.quote('http://www.baidu.com')
print(file)
quote=urllib.request.unquote('http%3A//www.baidu.com')
print(quote)
輸出為
D:\Python_code\env_pacong\Scripts\python.exe D:/Python_code/pachong/pachong1.py
http%3A//www.baidu.com
http://www.baidu.com
下面再來看一個典型的我的錯誤
import urllib.request
url = 'http://www.baidu.com'
file=urllib.request.urlopen('url')
print(file.text)
錯誤一urlopen里面是參數時不用引號
錯誤二urlopen里沒有text參數只有requests才有,別搞混了,urllib只有通過上面的read()才能讀而
import requests
url = 'http://www.baidu.com'
file=requests.get(url)
print(file.text)
request這樣就可以讀
好了,大概的urllib流程也會了,現在來點不一樣的吧
瀏覽器的模擬--Heathers屬性
因為一些網站原因不能爬取,這時需要我們模擬網站訪問
第一步打開你想要的網站點進去事件發生,然后檢查或者f12找到user-Agent把它復制下來比如bing的就是
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
import urllib.request
url ='http://blog.csdn.net/weiwei_pig/article/details/51178226'
req=urllib.request.Request(url)
req.add_header('user-agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36')
data=urllib.request.urlopen(req).read()
fhandle=open('D:/Python_code/pachong/handle/3.html','wb')
fhandle.write(data)
fhandle.close()
然后打開3.html就有了
方式二
import urllib.request
url='http://blog.csdn.net/weiwei_pig/article/details/51178226'
headers=('user-agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36')
opener=urllib.request.build_opener()
opener.addheaders=[headers]
data=opener.open(url).read()
fhandle=open('D:/Python_code/pachong/handle/4.html','wb')
fhandle.write(data)
fhandle.close()
一樣有了
-簡單的超時設置
file = urllib.request.urlopen('http://yum.iqianyue.com',timeout=1)
-http協議請求
1.GET請求
2.POST請求
3.PUT請求
4.DELETE請求
5.HEAD請求
- GET請求實例分析
keyworld = 'hello'
url = 'http://www.baidu.com/s?wd=' + keyworld
或者
kv={'wd':'python'}
r=urllib.request.urlopen('http://www.baidu.com/s',params=kv)
如果key是中文。編碼可能帶來問題,則需要解碼
import urllib.request
url='http://www.baidu.com/s?wd='
key='陽'
key_code=urllib.request.quote(key)
url_all=url+key_code
req=urllib.request.Request(url_all)
data=urllib.request.urlopen(req).read()
print(data)或者可以寫入文件也可以
- POST請求實例
import urllib.request
import urllib.parse
url='http://www.iqianyue.com/mypost/'
postdata=urllib.parse.urlencode({
'name':'yangjie',
'pass':'12345'
}).encode('utf-8')
req=urllib.request.Request(url,postdata)
req.add_header('user-agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36')
data=urllib.request.urlopen(req).read()
fhand=open('D:/Python_code/pachong/handle/5.html','wb')
fhand.write(data)
fhand.close()
編碼問題。
Python 默認腳本文件都是 ANSCII 編碼的,當文件 中有非 ANSCII 編碼范圍內的字符的時候就要使用"編碼指示"來修正一個 module 的定義中,如果.py文件中包含中文字符(嚴格的說是含有非anscii字符),則需要在第一行或第二行指定編碼聲明:# -- coding=utf-8 -- 或者 #coding=utf-8
python bytes和str兩種類型轉換的函數encode(),decode()
str通過encode()方法可以編碼為指定的bytes
反過來,如果我們從網絡或磁盤上讀取了字節流,那么讀到的數據就是bytes。要把bytes變為str,就需要用decode()方法:
是數據用decode不是連接url的response,
import urllib.request
file = urllib.request.urlopen('http://www.baidu.com')
data=file.read()
print(file.getcode())
結果為 200
我居然一開始打算用data.getcode()這個getcode()為狀態碼,只是用來檢查你是否連接成功沒有,而data是數據 。。。。。。。。。。。。。。。。
下面看經典的查看
import requests
r=requests.get('https://gs.amazon.cn/ref=as_cn_gs_topnav_reg?ld=AZCNAGSTopnav')
print(r.status_code)
回復
503
再用
print(r.encoding)
回復
'ISO-8859-1'
這時我們再用r.encoding=r.apparent_encoding
print(r.text)
就能看到返回提示錯誤,
:意外錯誤等
這就是網站不讓我們爬蟲瀏覽,所以就會有頭部的修改
來一個錯誤
>>>import urllib.request
>>>file = urllib.request.urlopen('http://www.baidu.com')
data=file.read()
print(data)
結果為 這種錯誤,空格和換行被打印出了
b'<!DOCTYPE html>\n<!--STATUS OK-->\n\r\n\r\n\r\n\r\n\r\n\
\n\n\n<html>\n<head>\n \n <meta http-equiv="content-type" co
但是我改了一點之后
你看
import urllib.request
file = urllib.request.urlopen('http://www.baidu.com')
data=file.read()
print(data.decode())
就好了 ,沒有了\n和\r,而且格式都整齊了如下
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
.....
后來經過百度
encode和decode分別指編碼和解碼
在python中,Unicode類型是作為編碼的基礎類型,即:
decode encode
str ---------> str(Unicode) ---------> str
1
2
>>> u = '中文' # 指定字符串類型對象u
>>> str1 = u.encode('gb2312') # 以gb2312編碼對u進行編碼,獲得bytes類型對象
>>> print(str1)
b'\xd6\xd0\xce\xc4'
>>> str2 = u.encode('gbk') # 以gbk編碼對u進行編碼,獲得bytes類型對象
>>> print(str2)
b'\xd6\xd0\xce\xc4'
>>> str3 = u.encode('utf-8') # 以utf-8編碼對u進行編碼,獲得bytes類型對象
>>> print(str3)
b'\xe4\xb8\xad\xe6\x96\x87'
>>> u1 = str1.decode('gb2312') # 以gb2312編碼對字符串str進行解碼,獲得字符串類型對象
>>> print('u1')
'中文'
>>> u2 = str1.decode('utf-8') # 報錯,因為str1是gb2312編碼的
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 0: invalid continuation byte
---------------------
可以看看這個
建立一個文件test.txt,文件格式用ANSI,內容為:"abc中文",用python來讀取
# coding=gbk
print open("Test.txt").read()
結果:abc中文
把文件格式改成UTF-8:
結果:abc涓 枃
顯然,這里需要解碼:
# coding=gbk
import codecs
print open("Test.txt").read().decode("utf-8")
結果:abc中文
還有
with open ('beautifulSoup_set.html','r',encoding='utf8') as f:
encoding為聲明文件編碼
r.encoding=r.apparent_encoding一般這樣就可以不用聲明了
再來一個例子吧
逆水城殤
python爬蟲解決gbk亂碼問題
今天嘗試了下爬蟲,爬取一本小說,忘語的凡人修仙仙界篇,當然這樣不好,大家要支持正版。
爬取過程中是老套路,先獲取網頁源代碼
復制代碼
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ =='__main__':
url='http://www.biquge.com.tw/18_18998/8750558.html'
page_req=requests.get(url)
html=page_req.text
bf=BeautifulSoup( html)
texts = bf.find_all('div',id='content')
print(texts[0].text.replace('\xa0'*8,'\n\n'))
復制代碼
結果:亂碼
在瀏覽器看下代碼,是gbk編碼,需要進行轉碼,這方面不清楚,查了下資料。
PS:爬取的所有網頁無論何種編碼格式,都轉化為utf-8格式進行存儲,與源代碼編碼格式不同所以出現亂碼
UTF-8通用性比較好,是用以解決國際上字符的一種多字節編碼,它對英文使用8位(即一個字節),中文使用24位(三個字節)來編碼。
UTF-8編碼的文字可以在各國各種支持UTF8字符集的瀏覽器上顯示,也就是必須兩者都是utf-8才行。
gbk是是國家編碼,通用性比UTF8差,GB2312之類的都算是gbk編碼。
GBK包含全部中文字符;UTF-8則包含全世界所有國家需要用到的字符。
unicode是一種二進制編碼,所有utf-8和gbk編碼都得通過unicode編碼進行轉譯,即utf-8和gbk編碼之間不能直接轉換。附圖如下:
python中編碼轉換用到了兩個函數decode()和encode()
比如:html=page_req.text.encode('iso-8859-1').decode('utf-8')
encode('iso-8859-1') 是將gbk編碼編碼成unicode編碼
decode(‘gbk’) 是從unicode編碼解碼成gbk字符串
由於pycharm只能顯示來自unicode的漢字,代碼修改如下:
復制代碼
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ =='__main__':
url='http://www.biquge.com.tw/18_18998/8750558.html'
page_req=requests.get(url)
html=page_req.text.encode('iso-8859-1')
bf=BeautifulSoup( html)
texts = bf.find_all('div',id='content')
print(texts[0].text.replace('\xa0'*8,'\n\n'))
復制代碼
最后解決:
最后再補充一點
raise_for_status()方法
理解Response類非常重要,Response這樣的一個對象返回了所有的網頁內容,那么它也提供了一個方法,叫raise_for_status(),這個方法是專門與異常打交道的方法,該方法有這樣一個有趣的功能,它能夠判斷返回的Response類型狀態是不是200。如果是200,他將表示返回的內容是正確的,如果不是200,他就會產生一個HttpError的異常。
那這個方法有什么用呢?
那我們來看一下我們的通用代碼框架:
>>> def getHTMLText(url):
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "產生異常"
這個代碼中我們用r.raise_for_status()方法,它就可以有效的判斷網絡連接的狀態。如果網連接出現錯誤,那么它就會用try-except來獲取一個異常。而這個異常,在異常部分,我們用了一句 return “產生異常” 來表示,我們捕獲到了這個異常,所以這樣一個通用代碼框架可以有效的處理,我們在訪問或爬取網頁過程中,它可能出現的一些錯誤,或者是網絡不穩定造成的一些現象。
其他
我們就可以使用chardet.detect()方法,判斷網頁的編碼方式了。至此,我們就可以編寫一個小程序判斷網頁的編碼方式了,新建文件名為chardet_test01.py:
# -*- coding: UTF-8 -*-
from urllib import request
import chardet
if __name__ == "__main__":
response = request.urlopen("http://fanyi.baidu.com/")
html = response.read()
charset = chardet.detect(html)
print(charset)
結果是 utf-8
然后再解碼就可以了
from urllib import request
if __name__ == "__main__":
response = request.urlopen("http://www.fanyi.baidu.com/")
html = response.read()
html = html.decode("utf-8")
print(html)
來看第一種requests庫以及它怎樣爬取一些基本的網頁
requests.request()構造一個請求
requests.get()獲取網頁主要內容
requests.head()獲取網頁頭部信息
還有post(),put(),delete()等
requests爬取的通用代碼框架
import requests
def getHTMLText(url):
try:
r=reqyests.get(url,timeout=30)
r.raise_for_status()
r.encoding=r.apparent_encoding
return r.text
except:
return '產生異常'
( r.raise_for_status()
r.encoding=r.apparent_encoding
后面有解釋)
詳細解釋下
requests.request(method,url,**kwargs)
**kwargs:控制訪問的參數,為可選項
params:字典或字節系列,作為參數增加到url中kv = {'key1':'values1','key2':'values2'}
r=requests.request('GET','http://python123.io/ws',params=kv)
print(r.url)
結果為
https://python123.io/ws?key1=values1&key2=values2
如果要中文需要這樣操作
body='主體內容'
body1=body.encode('utf8')
還可以讀取文件
fs={'file':open('data.xls','rb')}
r=requests.request('POST','http://python123.io/ws',files=fs)
設定訪問代理服務器
pxs={
'http':'http://uesr:pass@10.10.10.1:1234'
'http':'http://10.10.10.1:2323'}
r-requests.request('GET','http://www.baidu.com',proxies=pxs)
看完了requests.request,來看下其他類型如get
def get_html(url):
try:
r=requests.get(url,timeout=20)
r.raise_for_status()
r.encoding=r.apparent_encoding
return r.text
except:
print('錯誤')
return ''
你也許經常想為 URL 的查詢字符串(query string)傳遞某種數據。如果你是手工構建 URL,那么數據會以鍵/值對的形式置於 URL 中,跟在一個問號的后面。例如, httpbin.org/get?key=val。 Requests 允許你使用 params 關鍵字參數,以一個字符串字典來提供這些參數。舉例來說,如果你想傳遞 key1=value1 和 key2=value2 到 httpbin.org/get ,那么你可以使用如下代碼:
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
通過打印輸出該 URL,你能看到 URL 已被正確編碼:
print(r.url)
http://httpbin.org/get?key2=value2&key1=value1
注意字典里值為 None 的鍵都不會被添加到 URL 的查詢字符串里。
你還可以將一個列表作為值傳入:
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get('http://httpbin.org/get', params=payload)
print(r.url)
http://httpbin.org/get?key1=value1&key2=value2&key2=value3
Requests 會自動解碼來自服務器的內容。大多數 unicode 字符集都能被無縫地解碼。
當你訪問 r.text 之時,Requests 會使用其推測的文本編碼。你可以找出 Requests 使用了什么編碼,並且能夠使用r.encoding 屬性來改變它:
r.encoding
'utf-8'
r.encoding = 'ISO-8859-1'
如果你改變了編碼,每當你訪問 r.text ,Request 都將會使用 r.encoding 的新值。你可能希望在使用特殊邏輯計算出文本的編碼的情況下來修改編碼。比如 HTTP 和 XML 自身可以指定編碼。這樣的話,你應該使用 r.content 來找到編碼,然后設置 r.encoding 為相應的編碼。這樣就能使用正確的編碼解析 r.text 了。
- Requests 中也有一個內置的 JSON 解碼器,助你處理 JSON 數據:
import requests
r = requests.get('https://github.com/timeline.json')
r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...
如果 JSON 解碼失敗, r.json() 就會拋出一個異常。例如,響應內容是 401 (Unauthorized),嘗試訪問 r.json() 將會拋出 ValueError: No JSON object could be decoded 異常。
需要注意的是,成功調用 r.json() 並不意味着響應的成功。有的服務器會在失敗的響應中包含一個 JSON 對象(比如 HTTP 500 的錯誤細節)。這種 JSON 會被解碼返回。要檢查請求是否成功,請使用 r.raise_for_status() 或者檢查 r.status_code 是否和你的期望相同。
bad_r = requests.get('http://httpbin.org/status/404')
bad_r.status_code
404
如果發送了一個錯誤請求(一個 4XX 客戶端錯誤,或者 5XX 服務器錯誤響應),我們可以通過 Response.raise_for_status() 來拋出異常:r.raise_for_status()
None
又如 一個網上的列子
1import requests
2 from bs4 import BeautifulSoup
3
4 r = requests.get("http://www.baidu.com")
5 soup = BeautifulSoup(r.text,"html.parser")
6
7 print(soup.title)
但是不知道出於什么原因,這段代碼在同事電腦上運行良好,但是在我的電腦上運行 就會出現亂碼。
然后又去請教,只要再補充上這段代碼就可以完美運行了。
復制代碼
1 import requests
2 from bs4 import BeautifulSoup
3
4 r = requests.get("http://www.baidu.com")
5 r.raise_for_status()
6 r.encoding = r.apparent_encoding
7 soup = BeautifulSoup(r.text,"html.parser")
8
9 print(soup.title)
這是因為r.apparent_ecoding使當前的encoding變得一致
詳細可以參看后面
import requests
def get_content(url):
resp=requests.get(url)
return resp.text
url='http://jwc.sicnu.edu.cn/#'
content=get_content(url)
print('結果為',content)
或者加一個列表索引,以及其他操作
import requests
def get_content(url):
respons=requests.get(url)
return respons.text
url='https://www.baidu.com'
content=get_content(url)
content_len=len(content)
print('長度0-100',content[0:100])
print('長度為',content_len)
也可以通過同一個文件夾的形式調用其他文件的函數
如
import frist_get //另一個文件
url='http://www.baidu.com.cn'
thor_content=frist_get.get_content(url)
但是最好引入if__name=='__main__':
避免重復或者其他問題
這個上面的都是requests的基本爬取網頁內容,下面是將內容寫入文件中
方式一
寫入
f1=open('home_page.html','w',encoding='utf8')
f1.write(content)
f1.close
讀取
f2=open(home_page.html','r',encoding='utf8')
content_read=f2.read()
f2.close()
方式二
寫入
with open ('home_page.html','w',encoding='utf8')as f3:
f3.write(content)
讀取
with open('home_page.html','r',encoding='utf8')as f4:
content_read_2=f4.read()
以上呢差別就是with語句會幫我們進行清理,而且不僅可以用於文件操作還能其他場景
下面再來看一個運用字典,列表,元組,集合,循環,等的爬取
import requests
url_dict={
'電子工業出版社':'http://www.phei.com.cn/',
'在線資源':'http://www.phei',
'xyz':'www.baidu.com',
'網上書店1':'http://phei.com.cn/module/goods/wssd_index.jsp',
'網上書店2':'http://phei.com.cn/module/goods/wssd_index.jsp',
}
urls_list=[
('電子工業出版社','http://www.phei.com.cn/'),
('在線資源','http://www.phei'),
('xyz','www.baidu.com'),
('網上書店1','http://phei.com.cn/module/goods/wssd_index.jsp'),
('網上書店2','http://phei.com.cn/module/goods/wssd_index.jsp'),
]
crawled_url_for_dict=set()
for ind,name in enumerate(url_dict.keys()):
name_url=url_dict[name]
if name_url in crawled_url_for_dict:
print(ind,name,'已結抓取過了')
else:
try:
resp=requests.get(name_url)
except Exception as e:
print(ind,name,':',str(e)[0:50])
continue
content=resp.text
crawled_url_for_dict.add(name_url)
with open('bydict_'+name+',html','w',encoding='utf8') as f:
f.write(content)
print('完成抓取:{} {},內容長度{}'.format(ind,name,len(content)))
for u in crawled_url_for_dict:
print(u)
print('-'*50)
crawled_url_for_list=set()
for ind,tup in enumerate(urls_list):
name=tup[0]
name_url=tup[1]
if name_url in crawled_url_for_list:
print('已經打印過了')
else:
try:
resp=requests.get(name_url)
except Exception as e:
print(ind,name,':',str(e)[0:50])
continue
content=resp.text
crawled_url_for_list.add(name_url)
with open('bylist'+name+'.html','w',encoding='utf8')as f:
f.write(content)
print('抓取完成:{}{},內容長度為{}'.format(ind,name,len(content)))
for u in crawled_url_for_list:
print(u)
結果為
完成抓取:0 電子工業出版社,內容長度134
1 在線資源 : HTTPConnectionPool(host='www.phei', port=80): Max
2 xyz : Invalid URL 'www.baidu.com': No schema supplied. P
3 網上書店1 : HTTPConnectionPool(host='phei.com.cn', port=80): M
4 網上書店2 : HTTPConnectionPool(host='phei.com.cn', port=80): M
http://www.phei.com.cn/
--------------------------------------------------
抓取完成:0電子工業出版社,內容長度為134
1 在線資源 : HTTPConnectionPool(host='www.phei', port=80): Max
2 xyz : Invalid URL 'www.baidu.com': No schema supplied. P
3 網上書店1 : HTTPConnectionPool(host='phei.com.cn', port=80): M
4 網上書店2 : HTTPConnectionPool(host='phei.com.cn', port=80): M
http://www.phei.com.cn/
import requests
img_url='https://i0.hdslb.com/bfs/live/5934676.jpg@.webp?03132026'
response=requests.get(img_url)
print(response)
返回
<Response [200]>
定制請求頭
如果你想為請求添加 HTTP 頭部,只要簡單地傳遞一個 dict 給 headers 參數就可以了。
例如,在前一個示例中我們沒有指定 content-type:
url = 'https://api.github.com/some/endpoint'
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)
注意: 定制 header 的優先級低於某些特定的信息源,例如:
如果在 .netrc 中設置了用戶認證信息,使用 headers= 設置的授權就不會生效。而如果設置了auth= 參數,.netrc 的設置就無效了。
如果被重定向到別的主機,授權 header 就會被刪除。
代理授權 header 會被 URL 中提供的代理身份覆蓋掉。
在我們能判斷內容長度的情況下,header 的 Content-Length 會被改寫。
更進一步講,Requests 不會基於定制 header 的具體情況改變自己的行為。只不過在最后的請求中,所有的 header 信息都會被傳遞進去。
注意: 所有的 header 值必須是 string、bytestring 或者 unicode。盡管傳遞 unicode header 也是允許的,但不建議這樣做。
- 無法訪問的網頁可以通過設置報頭
import requests
r=requests.get('https://gs.amazon.cn/ref=as_cn_gs_topnav_reg?ld=AZCNAGSTopnav')
print(r.status_code)
回復
503
再用
print(r.encoding)
回復
'ISO-8859-1'
這時我們再用r.encoding=r.apparent_encoding//這使得當前返回的代碼變得是我們能看懂的代碼返回,就算錯誤也會返回而且能看懂,如果是正確的就會返回規范正確的代碼
print(r.text)
就能看到返回提示錯誤,
:意外錯誤等
這就是網站不讓我們爬蟲瀏覽,所以就會有頭部的修改
修改添加如下
kv={'uesr-agent':'Mozilla/5.0'}
url='https://gs.amazon.cn/ref=as_cn_gs_topnav_reg?ld=AZCNAGSTopnav'
r=requests.get(url,headers=kv)
r.status_code
返回200說明可以了
全部代碼如下
import requests
url= 'http://www.amazon.cn/gp/product/B01M8L5Z3Y'
try:
kv={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
r=requests.get(url,headers=kv)
r.raise_for_status()
r.encoding=r.apparent_encoding
print(r.text[0:2000])
except:
print('爬取失敗')
結果為
<!doctype html><html class="a-no-js" data-19ax5a9jf="dingo">
<head>
<script type="text/javascript">var ue_t0=ue_t0||+new Date();</script>
。。。。。。。等
連格式也是正確的
http協議請求
我們在瀏覽器用百度為例子輸入hello
發現為https://www.baidu.com/s?wd=hello&rsv_spt=1&rsv_iqid=0xcbd3ca2000079cac&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=7&rsv_sug1=6&rsv_sug7=100
keyworld='hello'
url='http://www.baidu.com/s?wd='+keyworld
req=requests.get(url)
print(req.text)
或者這樣
import requests
kv={'wd':'python'}
r=requests.get('http://www.baidu.com/s',params=kv)
print(r.status_code)
print(r.request.url)
(requests模塊發送請求有data、params兩種攜帶參數的方法。
params在get請求中使用,data在post請求中使用。)
結果為
D:\Python_code\env_pacong\Scripts\python.exe D:/Python_code/pachong/pachong1.py
200
http://www.baidu.com/s?wd=python
下面將它寫入文件 用requests
import requests
kv={'wd':'python'}
r=requests.get('http://www.baidu.com/s',params=kv)
r.encoding=r.apparent_encoding
with open('D:/Python_code/pachong/handle/2.html','wb')as f:
f.write(r.text)
print('下載完成')
報錯TypeError: a bytes-like object is required, not 'str'
python bytes和str兩種類型轉換的函數encode(),decode()
str通過encode()方法可以編碼為指定的bytes
反過來,如果我們從網絡或磁盤上讀取了字節流,那么讀到的數據就是bytes。要把bytes變為str,就需要用decode()方法:
然而只需要這樣就行了
import requests
kv={'wd':'python'}
r=requests.get('http://www.baidu.com/s',params=kv)
with open('D:/Python_code/pachong/handle/2.html','wb')as f:
f.write(r.content)
print('下載完成')
然后打開2.html 是python 的百度頁面 對的
整個只需要把text換content
可能因為content拿到的是二進制的形式而text是字符串
用requests下載圖片
import requests
import os
url='http://image.nationalgeographic.com.cn/2017/0211/20170211061910157.jpg'
root='D://pathon_code//pachong//'
文件根目錄
path=root+url.split('/')[-1]
用最后命名
try:
if not os.path.exists(root):
os.madir(root)
判斷目錄是否存在
if not os.path.exists(path):
判斷路徑是否存在
r=requests.get(url)
with open(path,'wb') as f:
f.write(r.content)
f.close()
print('文件保持成功')
else:
print('文件已經存在')
except:
print('爬取失敗')
下面將進行幾個爬取例子
1.爬取京東商品信息
以下是我的代碼
import requests
r=requests.get('https://item.jd.com/37230573868.html')
print(r.status_code)
print(r.encoding)
print(r.text[0:1000])
下面來看規范的代碼
import requests
url='https://item.jd.com/37230573868.html'
try:
r=requests.get(url)
r.raise_for_status()
r.encoding=r.apparent_encoding
print(r.text[:1000])
except:
print('爬取失敗')
雖然結果都一樣,但是這樣通過 r.raise_for_status()排除了異常,如果返回的代碼是200是不會有用的,否則就會產生異常,再通過try except這樣程序健壯性增強許多,而且通過r.encoding=r.apparent_encoding使得返回的代碼我們能看得懂,就算錯誤也會得到意外錯誤的代碼返回
下面來看爬取例子二
import requests
url= 'http://www.amazon.cn/gp/product/B01M8L5Z3Y'
try:
kv={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
r=requests.get(url,headers=kv)
r.raise_for_status()
r.encoding=r.apparent_encoding
print(r.text[0:2000])
except:
print('爬取失敗')
更加復雜的 POST 請求
通常,你想要發送一些編碼為表單形式的數據——非常像一個 HTML 表單。要實現這個,只需簡單地傳遞一個字典給 data 參數。你的數據字典在發出請求時會自動編碼為表單形式:
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=payload)
print(r.text)
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
你還可以為 data 參數傳入一個元組列表。在表單中多個元素使用同一 key 的時候,這種方式尤其有效:
payload = (('key1', 'value1'), ('key1', 'value2'))
r = requests.post('http://httpbin.org/post', data=payload)
print(r.text)
{
...
"form": {
"key1": [
"value1",
"value2"
]
},
...
}
很多時候你想要發送的數據並非編碼為表單形式的。如果你傳遞一個 string 而不是一個 dict,那么數據會被直接發布出去。
例如,Github API v3 接受編碼為 JSON 的 POST/PATCH 數據:
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
此處除了可以自行對 dict 進行編碼,你還可以使用 json 參數直接傳遞,然后它就會被自動編碼。這是 2.4.2 版的新加功能:
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, json=payload)
POST一個多部分編碼(Multipart-Encoded)的文件
Requests 使得上傳多部分編碼文件變得很簡單:
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
你可以顯式地設置文件名,文件類型和請求頭:
url = 'http://httpbin.org/post'
files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
r = requests.post(url, files=files)
r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
如果你想,你也可以發送作為文件來接收的字符串:
url = 'http://httpbin.org/post'
files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
r = requests.post(url, files=files)
r.text
{
...
"files": {
"file": "some,data,to,send\nanother,row,to,send\n"
},
...
}
如果你發送一個非常大的文件作為 multipart/form-data 請求,你可能希望將請求做成數據流。默認下 requests 不支持, 但有個第三方包 requests-toolbelt 是支持的。你可以閱讀 toolbelt 文檔來了解使用方法。
在一個請求中發送多文件參考 高級用法 一節。
警告
強烈建議你用二進制模式(binary mode)打開文件。這是因為 Requests 可能會試圖為你提供 Content-Length header,在它這樣做的時候,這個值會被設為文件的字節數(bytes)。如果用文本模式(text mode)打開文件,就可能會發生錯誤。
響應狀態碼
我們可以檢測響應狀態碼:
r = requests.get('http://httpbin.org/get')
r.status_code
200
為方便引用,Requests還附帶了一個內置的狀態碼查詢對象:
r.status_code == requests.codes.ok
True
如果發送了一個錯誤請求(一個 4XX 客戶端錯誤,或者 5XX 服務器錯誤響應),我們可以通過Response.raise_for_status() 來拋出異常:
bad_r = requests.get('http://httpbin.org/status/404')
bad_r.status_code
404
bad_r.raise_for_status()
Traceback (most recent call last):
File "requests/models.py", line 832, in raise_for_status
raise http_error
requests.exceptions.HTTPError: 404 Client Error
但是,由於我們的例子中 r 的 status_code 是 200 ,當我們調用 raise_for_status() 時,得到的是:
r.raise_for_status()
None
一切都挺和諧哈。
響應頭
我們可以查看以一個 Python 字典形式展示的服務器響應頭:
r.headers
{
'content-encoding': 'gzip',
'transfer-encoding': 'chunked',
'connection': 'close',
'server': 'nginx/1.0.4',
'x-runtime': '148ms',
'etag': '"e1ca502697e5c9317743dc078f67693f"',
'content-type': 'application/json'
}
但是這個字典比較特殊:它是僅為 HTTP 頭部而生的。根據 RFC 2616, HTTP 頭部是大小寫不敏感的。
因此,我們可以使用任意大寫形式來訪問這些響應頭字段:
r.headers['Content-Type']
'application/json'
r.headers.get('content-type')
'application/json'
它還有一個特殊點,那就是服務器可以多次接受同一 header,每次都使用不同的值。但 Requests 會將它們合並,這樣它們就可以用一個映射來表示出來,參見 RFC 7230:
A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma.
接收者可以合並多個相同名稱的 header 欄位,把它們合為一個 "field-name: field-value" 配對,將每個后續的欄位值依次追加到合並的欄位值中,用逗號隔開即可,這樣做不會改變信息的語義。
Cookie
如果某個響應中包含一些 cookie,你可以快速訪問它們:
url = 'http://example.com/some/cookie/setting/url'
r = requests.get(url)
r.cookies['example_cookie_name']
'example_cookie_value'
要想發送你的cookies到服務器,可以使用 cookies 參數:
url = 'http://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)
r.text
'{"cookies": {"cookies_are": "working"}}'
Cookie 的返回對象為 RequestsCookieJar,它的行為和字典類似,但界面更為完整,適合跨域名跨路徑使用。你還可以把 Cookie Jar 傳到 Requests 中:
jar = requests.cookies.RequestsCookieJar()
jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
url = 'http://httpbin.org/cookies'
r = requests.get(url, cookies=jar)
r.text
'{"cookies": {"tasty_cookie": "yum"}}'
重定向與請求歷史
默認情況下,除了 HEAD, Requests 會自動處理所有重定向。
可以使用響應對象的 history 方法來追蹤重定向。
Response.history 是一個 Response 對象的列表,為了完成請求而創建了這些對象。這個對象列表按照從最老到最近的請求進行排序。
例如,Github 將所有的 HTTP 請求重定向到 HTTPS:
r = requests.get('http://github.com')
r.url
'https://github.com/'
r.status_code
200
r.history
[<Response [301]>]
如果你使用的是GET、OPTIONS、POST、PUT、PATCH 或者 DELETE,那么你可以通過 allow_redirects 參數禁用重定向處理:
r = requests.get('http://github.com', allow_redirects=False)
r.status_code
301r.history
[]
如果你使用了 HEAD,你也可以啟用重定向:
r = requests.head('http://github.com', allow_redirects=True)
r.url
'https://github.com/'r.history
[<Response [301]>]
超時
你可以告訴 requests 在經過以 timeout 參數設定的秒數時間之后停止等待響應。基本上所有的生產代碼都應該使用這一參數。如果不使用,你的程序可能會永遠失去響應:
requests.get('http://github.com', timeout=0.001)
Traceback (most recent call last):
File "", line 1, in
requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
注意
timeout 僅對連接過程有效,與響應體的下載無關。 timeout 並不是整個下載響應的時間限制,而是如果服務器在 timeout 秒內沒有應答,將會引發一個異常(更精確地說,是在timeout 秒內沒有從基礎套接字上接收到任何字節的數據時)If no timeout is specified explicitly, requests do not time out.
錯誤與異常
遇到網絡問題(如:DNS 查詢失敗、拒絕連接等)時,Requests 會拋出一個 ConnectionError 異常。
如果 HTTP 請求返回了不成功的狀態碼, Response.raise_for_status() 會拋出一個 HTTPError異常。
若請求超時,則拋出一個 Timeout 異常。
若請求超過了設定的最大重定向次數,則會拋出一個 TooManyRedirects 異常。
所有Requests顯式拋出的異常都繼承自 requests.exceptions.RequestException 。
正則和BeautifulSoup的解析
正則表達式
兩個特殊的符號'^'和'$'。他們的作用是分別指出一個字符串的開始和結束。例子如下:
"^The":表示所有以"The"開始的字符串("There","The cat"等);
"of despair$":表示所以以"of despair"結尾的字符串;
"^abc$":表示開始和結尾都是"abc"的字符串——呵呵,只有"abc"自己了;
"notice":表示任何包含"notice"的字符串。
象最后那個例子,如果你不使用兩個特殊字符,你就在表示要查找的串在被查找串的任意部分——你並
不把它定位在某一個頂端。
其它還有'*','+'和'?'這三個符號,表示一個或一序列字符重復出現的次數。它們分別表示“沒有或
更多”,“一次或更多”還有“沒有或一次”。下面是幾個例子:
"ab*":表示一個字符串有一個a后面跟着零個或若干個b。("a", "ab", "abbb",……);
"ab+":表示一個字符串有一個a后面跟着至少一個b或者更多;
"ab?":表示一個字符串有一個a后面跟着零個或者一個b;
"a?b+$":表示在字符串的末尾有零個或一個a跟着一個或幾個b。
你也可以使用范圍,用大括號括起,用以表示重復次數的范圍。
"ab{2}":表示一個字符串有一個a跟着2個b("abb");
"ab{2,}":表示一個字符串有一個a跟着至少2個b;
"ab{3,5}":表示一個字符串有一個a跟着3到5個b。
請注意,你必須指定范圍的下限(如:"{0,2}"而不是"{,2}")。還有,你可能注意到了,'*','+'和
'?'相當於"{0,}","{1,}"和"{0,1}"。
還有一個'¦',表示“或”操作:
"hi¦hello":表示一個字符串里有"hi"或者"hello";
"(b¦cd)ef":表示"bef"或"cdef";
"(a¦b)*c":表示一串"a""b"混合的字符串后面跟一個"c";
'.'可以替代任何字符:
"a.[0-9]":表示一個字符串有一個"a"后面跟着一個任意字符和一個數字;
"^.{3}$":表示有任意三個字符的字符串(長度為3個字符);
方括號表示某些字符允許在一個字符串中的某一特定位置出現:
"[ab]":表示一個字符串有一個"a"或"b"(相當於"a¦b");
"[a-d]":表示一個字符串包含小寫的'a'到'd'中的一個(相當於"a¦b¦c¦d"或者"[abcd]");
"^[a-zA-Z]":表示一個以字母開頭的字符串;
"[0-9]%":表示一個百分號前有一位的數字;
",[a-zA-Z0-9]$":表示一個字符串以一個逗號后面跟着一個字母或數字結束。
你也可以在方括號里用''表示不希望出現的字符,''應在方括號里的第一位。(如:"%[^a-zA-Z]%"表示兩個百分號中不應該出現字母)。
為了逐字表達,你必須在"^.$()¦*+?{"這些字符前加上轉移字符''。
請注意在方括號中,不需要轉義字符。
2.正則表達式驗證控制文本框的輸入字符類型
1.只能輸入數字和英文的:
<input onkeyup="value=value.replace(/[\W]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))" ID="Text1" NAME="Text1">
2.只能輸入數字的:
<input onkeyup="value=value.replace(/[^\d]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))" ID="Text2" NAME="Text2">
3.只能輸入全角的:
<input onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))" ID="Text3" NAME="Text3">
4.只能輸入漢字的:
<input onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))" ID="Text4" NAME="Text4">
3.正則表達式的應用實例通俗說明
//校驗是否全由數字組成
/^[0-9]{1,20}$/
^ 表示打頭的字符要匹配緊跟^后面的規則
$ 表示打頭的字符要匹配緊靠$前面的規則
[ ] 中的內容是可選字符集
[0-9] 表示要求字符范圍在0-9之間
{1,20}表示數字字符串長度合法為1到20,即為[0-9]中的字符出現次數的范圍是1到20次。
/^ 和 $/成對使用應該是表示要求整個字符串完全匹配定義的規則,而不是只匹配字符串中的一個子串。
//校驗登錄名:只能輸入5-20個以字母開頭、可帶數字、“_”、“.”的字串
/^[a-zA-Z]{1}([a-zA-Z0-9]|[._]){4,19}$/
^[a-zA-Z]{1} 表示第一個字符要求是字母。
([a-zA-Z0-9]|[._]){4,19}
表示從第二位開始(因為它緊跟在上個表達式后面)的一個長度為4到9位的字符串,它要求是由大小寫字母、數字或者特殊字符集[._]組成。
//校驗用戶姓名:只能輸入1-30個以字母開頭的字串
/^[a-zA-Z]{1,30}$/
//校驗密碼:只能輸入6-20個字母、數字、下划線
/^(\w){6,20}$/
\w:用於匹配字母,數字或下划線字符
//校驗普通電話、傳真號碼:可以“+”或數字開頭,可含有“-” 和 “ ”
/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/
\d:用於匹配從0到9的數字;
“?”元字符規定其前導對象必須在目標對象中連續出現零次或一次
可以匹配的字符串如:+123 -999 999 ; +123-999 999 ;123 999 999 ;+123 999999等
//校驗URL
/^http[s]{0,1}:\/\/.+$/ 或 /^http[s]{0,1}:\/\/.{1,n}$/ (表示url串的長度為length(“https://”) + n )
\ / :表示字符“/”。
. 表示所有字符的集
+ 等同於{1,},就是1到正無窮吧。
再來一個檢驗以.com .cn結尾url
import re
pattern='[a-zA-Z]+://[^\s]*[.com|.cn]'
string="<a href='http://www.baidu.com'>百度首頁</a>"
result=re.search(pattern,string)
print(result)
\s為空白字符
[^\s]則為非空白字符
*匹配一次或多次前面的字符
下面再來看一個例子
import re
pattern1='p.*y' #貪婪模式
patton2='p.*?y' #懶惰模式
string ='abcdfphp124pythony_py'
result1=re.search(pattern1,string)
result2=re.search(patton2,string)
print(result1)
print(result2)
結果為
D:\Python_code\env_pacong\Scripts\python.exe D:/Python_code/pachong/pachong1.py
<re.Match object; span=(5, 21), match='php124pythony_py'>
<re.Match object; span=(5, 13), match='php124py'>
import re
string='adadjgdfsdkdasadfksskaasadadyfhlmbnlvzxxaewrtl'
pattern='.a.'
result=re.compile(pattern).findall(string)
print(result)
結果為
['dad', 'das', 'kaa', 'sad', 'xae']
再來看一個京東商品的經典例子
import urllib.request
import re
from bs4 import BeautifulSoup
def crawl(url,page):
headers={'url-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
req=urllib.request.Request(url=url,headers=headers)
html=urllib.request.urlopen(req).read()
html1=html.decode() #格式變得標准化。解碼
part1 = r'<div id="J_goodsList" .+?<div class="m-aside">'
result1 = re.compile(part1,flags=re.DOTALL).findall(html1)
result1=result1[0] #使數據變得工整而且格式化了 么以偶了/n等重復
part2=r'<img width="220" height="220" class="err-product" data-img="1" source-data-lazy-img="//(.+?\.jpg)" />'
imagelist=re.compile(part2).findall(result1)
x=1
for imageurl in imagelist:
imagename="D:/python_code/pachong/handle/jd_image/"+str(page)+str(x)+'.jpg'
imageurl='http://'+imageurl
try:
urllib.request.urlretrieve(imageurl,filename=imagename)
except urllib.error.URLError as e:
if hasattr(e,'code'):
x+=1
if hasattr(e,'reason'):
x+=1
x+=1
for i in range(1,5):
url='https://search.jd.com/Search?keyword=iphonex&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&suggest=1.his.0.0&page='+str(i)
crawl(url,i)
print('第i爬取成功')
經過艱難的終於寫好這用第一個爬蟲爬取圖片
下面回顧下寫的時候的問題
1正則表達式出現了問題
我在京東商品的頁面源代碼用ctrl+f也找了
下面的標志只有一個也就是只有一次出現正好滿足條件
part1 = r'<div id="J_goodsList" .+?<div class="m-aside">'
result1 = re.compile(part1).findall(html1)
一開始我是這樣寫的,但是一直返回我一個[]然后百度很久終於知道為什么
這個問題一般出現在希望使用句點(.)來匹配任意字符,但是忘記了句點並不能匹配換行符時:
import re
comment = re.compile(r'/\*(.*?)\*/') # 匹配C的注釋
text1 = '/* this is a comment */'
text2 = """/*this is a
multiline comment */"""
comment.findall(text1)
Out[4]: [' this is a comment ']
comment.findall(text2) # 由於text2文本換行了,沒匹配到
Out[5]: []
解決方法1:添加對換行符的支持,(?:.|\n)指定了一個非捕獲組(即,這個組只做匹配但不捕獲結果,也不會分配組號)
comment = re.compile(r'\*((?:.|\n)*?)\*/')
comment.findall(text2)
Out[7]: ['this is a \n multiline comment ']
解決方法2:re.compile()函數可接受一個有用的標記--re.DOTALL。這使得正則表達式中的句點(.)可以匹配所有的字符,也包括換行符
comment = re.compile(r'/\*(.*?)\*/', flags=re.DOTALL)
comment.findall(text2)
Out[10]: ['this is a \n multiline comment ']
很明顯我就是用的第二種然后終於正則表達式成功的匹配了我想要的
爬取了想要的大概內容但是還不是我想要的圖片url
但是發現每個頁面的圖片URL都在<img width="220" height="220" class="err-product" data-img="1" source-data-lazy-img="//img12.360buyimg.com/n7/jfs/t1/38769/36/65/76968/5cb83ffeEe5900ad2/ee8924e4c5a0fd03.jpg" />
這里面,我用ctrl+f搜索source-data-lazy-img=找到他們
但是怎么用正則表達式找出他們那,
經過排查發現所有的圖片鏈接都一樣除了img12.360buyimg.com/n7/jfs/t1/38769/36/65/76968/5cb83ffeEe5900ad2/ee8924e4c5a0fd03.jpg"
這一段,所以這一段用.+?代替,而且千萬別這里也用flags=re.DOTALL
會多一些莫名其妙的數據
如果是這樣
part2=r'<img width="220" height="220" class="err-product" data-img="1" source-data-lazy-img="//(.+?).jpg" />'
imagelist=re.compile(part2).findall(result1)
print(imagelist)
那結果為
['img14.360buyimg.com/n7/jfs/t1/4528/10/3590/153299/5b997bf5E4a513949/45ab3dd6c35d981b', 'img13.360buyimg.com/n7/jfs/t10675/253/1344769770/66891/92d54ca4/59df2e7fN86c99a27',
這沒有后面的.jpg,
所以我用這樣
part2=r'<img width="220" height="220" class="err-product" data-img="1" source-data-lazy-img="//(.+?\.jpg)" />'
imagelist=re.compile(part2).findall(result1)
print(imagelist)
結果就是正確的咯
['img13.360buyimg.com/n7/jfs/t10675/253/1344769770/66891/92d54ca4/59df2e7fN86c99a27.jpg', 'img13.360buyimg.com/n7/jfs/t10690/249/1626659345/69516/b3643998/59e4279aNff3d63ac.jpg',
但是需要轉義\因為有特殊字符.而且需要一個()把正則表達式和.jpg一起
爬取鏈接
import re
import urllib.request
def getlink(url):
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
req=urllib.request.Request(url=url,headers=headers)
html=urllib.request.urlopen(req).read().decode()
print('================================')
part='(https?://[^\s)";]+\.(\w|/)*)'
#?指https或者http
#[^\s)";]指不可以出現空格\s不出現雙引號,分號
link=re.compile(part).findall(html)
linklist=list(set(link))
for link in linklist:
print(link[0])
<!-- 修改
part='((https|http)://[^\s)";]+\.(\w|/)*)'
匹配更多鏈接 -->
url='http://blog.csdn.net/'
getlink(url)
爬取糗事百科
import urllib.request
import re
import urllib.request
def getcontent(url,i):
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
req=urllib.request.Request(url=url,headers=headers)
html=urllib.request.urlopen(req).read().decode()
print('================================')
part1='<div class="content">(.*?)</span>'
content=re.compile(part1,flags=re.DOTALL).findall(html)
print(content)
for i in range(1,5):
url='https://www.qiushibaike.com/text/page/'+str(i)
getcontent(url,i)
BeautifulSoup庫解析html/xml文檔
首先BeautifulSoup有四種解析庫,
1.python標准庫 使用方法BeautifulSoup(markup,'html.parser')
2.lxml HTML解析器 使用方法BeautifulSoup(markup,'lxml')速度快,文檔容錯能力強,需要安裝c語言庫(推薦使用)
3 . lxml XML解析器 使用方法 BeautifulSoup(markup,'xml;)唯一支持XML的解析器,需要安裝c語言庫
4.html5lib 使用方法BeautifulSoup(markup,'hml5lib')最后的容錯性,以瀏覽器的方式解析文檔,生成html5格式,速度慢
- 基本使用
建議使用lxml
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.prettify())
格式化和自動補齊
print(soup.title.string)
輸出title 的內容
下面介紹常用的選擇器
- 第一種 ---標簽選擇器
1 .獲取標簽
如選擇標簽a li ul class p等或者子節點或者父節點等
import requests
from bs4 import BeautifulSoup
r=requests.get('http://python123.io/ws/demo.html')
demo=r.text
soup =BeautifulSoup(demo,'html.parser')
這里指定解析器是html的parser
print(soup.prettify())
prettify()函數能為html做換行符也能為每一個標簽做格式
結果為
<html>
<head>
<title>
This is a python demo page
</title>
</head>
<body>
<p class="title">
<b>
The demo python introduces several python courses.
</b>
</p>
<p class="course">
Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">
Basic Python
</a>
and
<a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">
Advanced Python
</a>
.
</p>
</body>
</html>
如果是打開文件的格式就為
soup2=BeautifulSoup(open('D://demo.html'),'html.parser')
下面詳細看看BeautifulSoup的對於html的便簽
import requests
from bs4 import BeautifulSoup
r=requests.get('http://python123.io/ws/demo.html')
demo=r.text
soup =BeautifulSoup(demo,'html.parser')
print(soup.title)
print('========================')
print(soup.a)
print('========================')
print(soup.a.name)
print('========================')
print(soup.a.parent.name)
print('========================')
print(soup.a.parent.parent.name)
結果為
<title>This is a python demo page</title>
========================
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
========================
a
========================
p
========================
body
BeautifulSoup實際上是以樹形圖解釋
如
下行遍歷
import requests
from bs4 import BeautifulSoup
r=requests.get('http://python123.io/ws/demo.html')
demo=r.text
soup =BeautifulSoup(demo,'html.parser')
print(soup.head)
結果為
<head><title>This is a python demo page</title></head>
若為
print(soup.head.contents)
結果為
[<title>This is a python demo page</title>]
平行遍歷
import requests
from bs4 import BeautifulSoup
r=requests.get('http://python123.io/ws/demo.html')
demo=r.text
soup =BeautifulSoup(demo,'html.parser')
print(soup.a)
print('============')
print(soup.a.next_sibling)
print('=========')
print(soup.a.next_sibling.next_sibling)
結果為
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
============
and
=========
<a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>
- 獲取屬性
import requests
from bs4 import BeautifulSoup
r=requests.get('http://python123.io/ws/demo.html')
demo=r.text
soup =BeautifulSoup(demo,'html.parser')
tag=soup.a
print(tag.attrs)
結果為
{'href': 'http://www.icourse163.org/course/BIT-268001', 'class': ['py1'], 'id': 'link1'}
他是以字典返回
所以可以這樣
print(soup.find_all(attrs={"id":"1"}))
在lxml也可以這樣
print(soup.find_all(attrs={id="1"}))
如果是關鍵字得加_如print(soup.find_all(attrs={class_="1"}))
也可以使用[]
如
print(soup.p.attrs['name'])=print(soup.p['name'])
bs4的信息提取
說完了大概方式 下面來一個例子爬取所有的url鏈接
import requests
from bs4 import BeautifulSoup
r=requests.get('http://python123.io/ws/demo.html')
demo=r.text
soup =BeautifulSoup(demo,'html.parser')
for link in soup.find_all('a'):
print(link.get('href'))
結果為
http://www.icourse163.org/course/BIT-268001
http://www.icourse163.org/course/BIT-1001870001
當然還可以結合re正則表達式
import requests
import re
from bs4 import BeautifulSoup
r=requests.get('http://python123.io/ws/demo.html')
demo=r.text
soup =BeautifulSoup(demo,'html.parser')
for tag in soup.find_all(re.compile('b')):
print(tag.name)
結果為
body
b
完美配合找出b的標簽名字
當然還可以通過這樣來查找
print(soup.find_all(id='link1'))
結果為
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>]
最后 bs4的編碼為utf8所以與python3.上完美符合就算中文也能無需解決編碼問題
lxml解析器中也支持css選擇器
運用select選擇‘
如
print(soup.select('ul li'))
中間一個空格隔開
若一個id='list-2'直接可以選擇內容 --加#
print(soup.select('#list-2.element'))
也可以用中括號獲得屬性
print(soup.select(ul['id']))
獲得內容也可以用get_text()
print(soup.select(li.get_text()))
也可以拖過這樣查找
soup = BeautifulSoup(response.text, "html.parser")
student_number = soup.find("span", id="lblStdNum")
源代碼如下
<td align="center" style="font-size: 12px;">
學 號:
</td>
<td>
<span id="lblStdNum" style="font-size:12px;"></span>
</td>
最后再student['number'] = student_number.text
就能過的學號
XPATH
首先,python 具有一些比較流行的解析庫,例如 lxml , 使用的是 XPath 語法,是大眾普遍認為的網頁文本信息提取的爬蟲利器之一。
一. 關於 XPath
XPath 是 XML路徑語言(XML Path Language),支持 HTML,是一種用來確定XML文檔中某部分位置的語言。XPath基於XML的樹狀結構,提供在數據結構樹中查找節點的能力。Xpath 可以通過元素和屬性進行導航,相比 正則表達式,它同樣可以在 XML 文檔中查詢信息,甚至使用起來更加簡單高效。
對於一個 XML 文件( HTML 文件可以通過 etree.HTML()方法 轉為這種格式)
如:# 使用etree對html解析
tree = etree.HTML(pageCode)
表達式 描述
nodename 選取此節點的所有子節點。
/ 從根節點選取。
// 從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。
. 選取當前節點。
.. 選取當前節點的父節點。
@ 選取屬性
!
下面再來看看幾個實例並理解xpath
import requests
from lxml import etree
# 設計模式 --》面向對象編程
class Spider(object):
def __init__(self):
# 反反爬蟲措施,加請求頭部信息
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
"Referer": "https://www.mzitu.com/xinggan/"
}
def xpath_data(self, html):
# 2. 抽取想要的數據 標題 圖片 xpath
src_list = html.xpath('//ul[@id="pins"]/li/a/img/@data-original')
alt_list = html.xpath('//ul[@id="pins"]/li/a/img/@alt')
for src, alt in zip(src_list, alt_list):
file_name = alt + ".jpg"
response = requests.get(src, headers=self.headers)
# 3. 存儲數據 jpg with open
try:
with open('D:/Python_code/pachong/handle/mzitu/'+file_name, "wb") as f:
f.write(response.content)
print("正在抓取圖片:" + file_name)
except:
print("==========文件名有誤!==========")
def start_request(self):
# 1. 獲取整體網頁的數據 requests
for i in range(1, 5):
print("==========正在抓取%s頁==========" % i)
response = requests.get("https://www.mzitu.com/page/" + str(i) + "/", headers=self.headers)
html = etree.HTML(response.content.decode())
self.xpath_data(html)
spider = Spider()
spider.start_request()
和
import requests
import threading
from bs4 import BeautifulSoup
import re
from lxml import etree
class tieba(object):
#1初始化,傳參作用等
def __init__(self,query_string):
self.query_string=query_string
self.url='https://tieba.baidu.com/f'
self.headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'}
#2
def parse_data(self,data,rule):
html_data=etree.HTML(data)
data_list=html_data.xpath(rule)
return data_list
#3
def seve_data(self,data,name):
path='D:/Python_code/pachong/handle/tieba/'+name
with open (path,'wb') as f:
f.write(data)
print("%s爬取完成" %name )
#4
def params(self):
para={
'kw':self.query_string
}
return para
def send_request(self,url,parms={}):
response=requests.get(url,params=parms,headers=self.headers)
return response.content
def run(self):
tieba_params=self.params()
datas=self.send_request(self.url,tieba_params)
#re
html=datas.decode()
url_list=re.compile('<a rel="noreferrer" href="(.+)" title.*?</a>').findall(html)
# xpath
# detail_rule="//div[@class='t_con cleafix']/div/div/div/a/@href"
# url_list=self.parse_data(datas,detail_rule)
for url in url_list:
detail_url='https://tieba.baidu.com'+url
detail_data=self.send_request(detail_url)
image_url='//img[@class="BDE_Image"]/@src'
image_url_list=self.parse_data(detail_data,image_url)
for image_url_1 in image_url_list:
image_data=self.send_request(image_url_1)
image_name=image_url_1[-12:]
self.seve_data(image_data,image_name)
if __name__ == '__main__':
a=input('請輸入你要的關鍵字')
tieba=tieba(a)
tieba.run()
Selenium 是為了測試而出生的. 但是沒想到到了爬蟲的年代, 它搖身一變, 變成了爬蟲的好工具. 讓我試着用一句話來概括 Seleninm: 它能控制你的瀏覽器, 有模有樣地學人類”看”網頁.
那么你什么時候會要用到 Selenium 呢? 當你:
發現用普通方法爬不到想要的內容
網站跟你玩”捉迷藏”, 太多 JavaScript 內容
需要像人一樣瀏覽的爬蟲
我是通過Anaconda寫selenium所以我只需要! pip install selenium
selenium的環境搭建需要瀏覽器的支持和瀏覽器driver的支持,我就同的chrome所以我必須下載chromedriver添加到path里即我加的是我的python的Script里就可以了
詳情參考百度python selenium
或者https://selenium-python.readthedocs.io/
下面運行第一個selenium
from selenium import webdriver
import time
firefox=webdriver.Chrome()
url='http://www.phei.com.cn/'
firefox.get(url)
time.sleep(10)
with open('phei.html','w',encoding='utf8')as f:
f.write(firefox.page_source)
firefox.quit()
就利用chrome打開了一個html
本地還有一個phei.html
查找單個元素
from selenium import webdriver
browser=webdriver.Chrome()
browser.get('https://www.taobao.com')
input_frist=browser.find_element_by_id('q')
input_second=browser.find_element_by_css_selector('#q')
print(input_frist,input_second)
browser.close()
結果為
<selenium.webdriver.remote.webelement.WebElement (session="fa3593cb1ecbf4e6e7b70570b9b23b27", element="0.7509356911593199-1")> <selenium.webdriver.remote.webelement.WebElement (session="fa3593cb1ecbf4e6e7b70570b9b23b27", element="0.7509356911593199-1")>
多個元素
from selenium import webdriver
browser=webdriver.Chrome()
browser.get('https://www.taobao.com')
lis=browser.find_elements_by_css_selector('.service-bd li')
print(lis)
browser.close()
里面的.service-bd li'是淘寶導航條的一個區域的名字
結果為
[<selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-1")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-2")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-3")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-4")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-5")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-6")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-7")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-8")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-9")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-10")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-11")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-12")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-13")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-14")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-15")>, <selenium.webdriver.remote.webelement.WebElement (session="38dc04f1721619c75b9957d0bcab5366", element="0.16647184484271205-16")>]
獲取了導航條的一大推
當然還可以加載時控制加載 比如不加載圖片如
# -*- coding:utf-8 -*-
from selenium import webdriver
'''
設置頁面不加載圖片,這樣可以加快頁面的渲染,減少爬蟲的等待時間,提升爬取效率
固定配置如下:
'''
chrome_opt = webdriver.ChromeOptions()
prefs = {'profile.managed_default_content_settings.images': 2}
chrome_opt.add_experimental_option('prefs',prefs)
# webdriver.Chrome(executable_path='path')啟動失敗的話,可以指定ChromeDriver驅動的位置path路徑
browser = webdriver.Chrome(chrome_options=chrome_opt)
# 啟動淘寶測試結果
browser.get('https://www.taobao.com')
界面跳轉
from selenium import webdriver
import time
browser=webdriver.Chrome()
browser.get('https://www.taobao.com')
input=browser.find_element_by_id('q')
input.send_keys('iphone')
time.sleep(1)
input.clear()
input.send_keys('ipad')
button=browser.find_element_by_class_name('search-button')
button.click()
程序執行后淘寶自動點擊進入了ipad的頁面
search-button就是淘寶源代碼里面的按鈕
click()就是selenium提供的api的方法
同理還有許多 如click_and_hold點擊之后不動double_click雙擊等相關api
獲得標簽內容,文本值
from selenium import webdriver
browser=webdriver.Chrome()
url='https://www.zhihu.com/explore'
browser.get(url)
input=browser.find_element_by_class_name('zu-top-add-question')
print(input.text)
print(input.id)
print(input.tag_name)
print(input.location)
輸出 為
提問
0.7567384595049704-1
button
{'x': 759, 'y': 7}
源代碼是<button class="zu-top-add-question" id="zu-top-add-question">提問</button>
前進和后退
from selenium import webdriver
import time
browser=webdriver.Chrome()
browser.get('https://www.bing.com/')
browser.get('https://www.taobao.com/')
browser.get('https://s.taobao.com/search?q=iphone&imgfile=&commend=all&ssid=s5-e&search')
time.sleep(1)
browser.back()
browser.back()
browser.forward()
browser.close()
選項卡
import time
from selenium import webdriver
browser=webdriver.Chrome()
browser.get('https://www.bing.com/')
browser.execute_script('window.open()')
#運用js的腳本可以切換和多個窗口
print(browser.window_handles)
browser.switch_to_window(browser.window_handles[1])
browser.get('https://www.taobao.com')
time.sleep(2)
browser.switch_to_window(browser.window_handles[0])
browser.get('https://python.org')
多個頁面,並且可以自動跳轉
下面再來一個selenium的抓取淘寶信息
1.Opener
當你獲取一個URL你使用一個opener。在前面,我們都是使用的默認的opener,也就是urlopen。它是一個特殊的opener,可以理解成opener的一個特殊實例,傳入的參數僅僅是url,data,timeout。
如果我們需要用到Cookie,只用這個opener是不能達到目的的,所以我們需要創建更一般的opener來實現對Cookie的設置。
2.Cookiejar
cookiejar模塊的主要作用是提供可存儲cookie的對象,以便於與urllib模塊配合使用來訪問Internet資源。Cookiejar模塊非常強大,我們可以利用本模塊的CookieJar類的對象來捕獲cookie並在后續連接請求時重新發送,比如可以實現模擬登錄功能。該模塊主要的對象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。
它們的關系:CookieJar —-派生—->FileCookieJar —-派生—–>MozillaCookieJar和LWPCookieJar
下面來看看書中的代碼】
import urllib.request
import urllib.parse
import http.cookiejar
url='*********************'
postdata=urllib.paser.urlencode({
'username':'weisuen',
'password':'aA123456'
}).encode('utf-8')
req=urllib.request.Request(url,postdata)
req.add_header('user-agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36')
#創建一個cookiejar對象
cjar=http.cookiejar.CookieJar()
#使用HTTPCookieProcessor創建cookie處理器,並以其構建參數作為opener
opener =urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cjar))
#將opener安裝為全局
urllib.request.install_opener(opener)
file=opener.open(req)
data=file.read()
cookiejar主要步驟
1.導入Cookie處理模塊http.cookiejar
2.使用http.cookiejar.CookieJar()創建CookieJar對象
3.使用HTTPCookieProcessor創建cookie處理器,並以其為參數構建opener對象
4.創建全局默認的opener對象
1)獲取Cookie保存到變量
首先,我們先利用CookieJar對象實現獲取cookie的功能,存儲到變量中,先來感受一下
from urllib import request
from urllib import parse
from http import cookiejar
#聲明一個CookieJar對象實例來保存cookie
cookie = cookiejar.CookieJar()
#利用urllib庫中的request的HTTPCookieProcessor對象來創建cookie處理器
handler=request.HTTPCookieProcessor(cookie)
#通過handler來構建opener
opener = request.build_opener(handler)
#此處的open方法同urllib的urlopen方法,也可以傳入request
response = opener.open('http://www.baidu.com')
for item in cookie:
print ('Name = '+item.name)
print ('Value = '+item.value)
我們使用以上方法將cookie保存到變量中,然后打印出了cookie中的值,運行結果如下
Name = BAIDUID
Value = 5C63AF95C94F5EE96BC89EE5E9CE0188:FG=1
Name = BIDUPSID
Value = 5C63AF95C94F5EE96BC89EE5E9CE0188
Name = H_PS_PSSID
Value = 1431_24557_21123_24022_20928
Name = PSTM
Value = 1508901974
Name = BDSVRTM
Value = 0
Name = BD_HOME
Value = 0
2)保存Cookie到文件
在上面的方法中,我們將cookie保存到了cookie這個變量中,如果我們想將cookie保存到文件中該怎么做呢?這時,我們就要用到
FileCookieJar這個對象了,建立LWPCookieJar實例,可以存Set-Cookie3類型的文件。而MozillaCookieJar類是存為'.txt'格式的文件.在這里我們使用它的子類MozillaCookieJar來實現Cookie的保存
#!/usr/bin/env/python
#encoding: UTF-8
from urllib import request
from urllib import parse
from http import cookiejar
#設置保存cookie的文件,同級目錄下的cookie.txt
filename = 'cookie.txt'
#聲明一個MozillaCookieJar對象實例來保存cookie,之后寫入文件
cookie = cookiejar.MozillaCookieJar(filename)
#利用urllib庫的HTTPCookieProcessor對象來創建cookie處理器
handler = request.HTTPCookieProcessor(cookie)
#通過handler來構建opener
opener = request.build_opener(handler)
#創建一個請求,原理同urllib2的urlopen
response = opener.open("http://www.baidu.com")
#保存cookie到文件
cookie.save(ignore_discard=True, ignore_expires=True)
關於最后save方法的兩個參數在此說明一下:
官方解釋如下:
ignore_discard: save even cookies set to be discarded.
ignore_expires: save even cookies that have expiredThe file is overwritten if it already exists
由此可見,ignore_discard的意思是即使cookies將被丟棄也將它保存下來,ignore_expires的意思是如果在該文件中cookies已經存在,則覆蓋原文件寫入,在這里,我們將這兩個全部設置為True。運行之后,cookies將被保存到cookie.txt文件中,我們查看一下內容,附圖如下
使用LWPCookieJar來保存cookie:
filename = 'cookie'
cookie = cookiejar.LWPCookieJar(filename)
使用的時候直接load。
3)從文件中獲取Cookie並訪問
那么我們已經做到把Cookie保存到文件中了,如果以后想使用,可以利用下面的方法來讀取cookie並訪問網站,感受一下
#!/usr/bin/env/python
#encoding: UTF-8
from urllib import request
from urllib import parse
from http import cookiejar
cookie = cookiejar.MozillaCookieJar()
cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
req= request.Request('http://www.baidu.com')
opener = request.build_opener(request.HTTPCookieProcessor(cookie))
response = opener.open(req)
print(response.read())
設想,如果我們的 cookie.txt 文件中保存的是某個人登錄百度的cookie,那么我們提取出這個cookie文件內容,就可以用以上方法模擬這個人的賬號登錄百度。
4)利用cookie模擬網站登錄
下面我們以知乎為例,利用cookie實現模擬登錄,來感受一下cookie大法吧!
#!/usr/bin/env/python
#encoding: UTF-8
import re
import requests
import http.cookiejar
from PIL import Image
import time
import json
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36',
"Host": "www.zhihu.com",
"Referer": "https://www.zhihu.com/",
}
# 建立一個會話,可以把同一用戶的不同請求聯系起來;直到會話結束都會自動處理cookies
session = requests.Session()
# 建立LWPCookieJar實例,可以存Set-Cookie3類型的文件。
# 而MozillaCookieJar類是存為'/.txt'格式的文件
session.cookies = http.cookiejar.LWPCookieJar("cookie")
# 若本地有cookie則不用再post數據了
try:
session.cookies.load(ignore_discard=True)
except IOError:
print('Cookie未加載!')
def get_xsrf():
"""
獲取參數_xsrf
"""
response = session.get('https://www.zhihu.com', headers=headers)
html = response.text
get_xsrf_pattern = re.compile(r'<input type="hidden" name="_xsrf" value="(.*?)"')
_xsrf = re.findall(get_xsrf_pattern, html)[0]
return _xsrf
def get_captcha():
"""
獲取驗證碼本地顯示
返回你輸入的驗證碼
"""
t = str(int(time.time() * 1000))
captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
response = session.get(captcha_url, headers=headers)
with open('cptcha.gif', 'wb') as f:
f.write(response.content)
# Pillow顯示驗證碼
im = Image.open('cptcha.gif')
im.show()
captcha = input('本次登錄需要輸入驗證碼: ')
return captcha
def login(username, password):
"""
輸入自己的賬號密碼,模擬登錄知乎
"""
# 檢測到11位數字則是手機登錄
if re.match(r'\d{11}$', username):
url = 'http://www.zhihu.com/login/phone_num'
data = {'_xsrf': get_xsrf(),
'password': password,
'remember_me': 'true',
'phone_num': username
}
else:
url = 'https://www.zhihu.com/login/email'
data = {'_xsrf': get_xsrf(),
'password': password,
'remember_me': 'true',
'email': username
}
# 若不用驗證碼,直接登錄
result = session.post(url, data=data, headers=headers)
# 打印返回的響應,r = 1代表響應失敗,msg里是失敗的原因
# loads可以反序列化內置數據類型,而load可以從文件讀取
if (json.loads(result.text))["r"] == 1:
# 要用驗證碼,post后登錄
data['captcha'] = get_captcha()
result = session.post(url, data=data, headers=headers)
print((json.loads(result.text))['msg'])
# 保存cookie到本地
session.cookies.save(ignore_discard=True, ignore_expires=True)
def isLogin():
# 通過查看用戶個人信息來判斷是否已經登錄
url = "https://www.zhihu.com/settings/profile"
# 禁止重定向,否則登錄失敗重定向到首頁也是響應200
login_code = session.get(url, headers=headers, allow_redirects=False).status_code
if login_code == 200:
return True
else:
return False
if __name__ == '__main__':
if isLogin():
print('您已經登錄')
else:
account = input('輸入賬號:')
secret = input('輸入密碼:')
login(account, secret)
以上程序的原理如下
創建一個帶有cookie的opener,在訪問登錄的URL時,將登錄后的cookie保存下來,然后利用這個cookie來訪問其他網址。
如登錄之后才能查看的成績查詢呀,本學期課表呀等等網址,模擬登錄就這么實現啦,是不是很酷炫?
在這之前,通過Django學習了mysql也對他有了一點了解,下面來看看爬蟲經常用的數據庫mongoDB
首先是安裝mongoDB,直接進入官網,然后下載相應版本的commiunity 社區版,然后一路install和next 切記,位置一定在根目錄下,不然最后的時候如果出現錯誤然后就會有三個文件分別是bin data log,而且最好把mongo db的compass一起下載好,默認的的是http://localhost:27017下載完成后打開目錄就有一個bin和log,data了,可以在bin里面cmd打開命令行輸入mongo就進入了mongodb的數據庫,如果沒有進入則mongod --dbpath 位置 就OK了,在數據庫里面輸入db就可以看見有一個test就可以對它進行增刪除之列的,就開啟了mongodb 的學習之路
而我的電腦連接mongodb兩種方法 ,第一種直接用命令mongod--dbpath E:\data或者直接搜索服務找到mondodb server 打開即可,如果要打開mysql參考Django
db.test.insert(('a':'b'))等基本操作忘了自己百度
1.安裝也可以sudo apt - get install mongodb - server
最好還是官網,新版本除了后自動配置好了,只需要下載就行了
2.指定數據庫位置即data,這個也是閃退后解決辦法之一在bin里面cmd執行
mongod --dbpath 位置 就OK了
3. python為了連接mongo DB 需要pymongo, pip install pymongo
4.import pymongo
client=pymongo.MongoClient('127.0.0.1',27017)連接客戶端
當然也可以client=pymongo.MongoClient('localhost',port=27017)
5.db=client['shujuku_name']創建一個數據庫,有就用這個數據庫,沒有就自動創建
db['biaodan_name'].insert(result)
1.准備好需要轉換的py文件和一張用於做圖標的照片,將他們存放於同一個文件夾中,文件的路徑全部為英文路徑
2.在網上將圖標裝換為.ico格式
3.利用命令窗口安裝pyinstaller插件 pip install
4.將命令窗口路徑切換到需要處理的py文件的路徑,使用cd命令來完成
5.執行命令 pyinstaller -F -i 1.ico 2.py(即ico和py的名字)
6.執行完命令后,需要的exe文件就在dist文件夾中
首先下載redis直接搜索redis安裝,有一個菜鳥教程還可以,點擊進入一個github, https://github.com/MSOpenTech/redis/releases。找到想要的發行版本,安裝下載即可,然后在github搜索redis desktop安裝可視化界面,強調下,我的都是在E盤的根目錄。
京東圖片
import urllib.request
import re
from bs4 import BeautifulSoup
def crawl(url,page):
headers={'url-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
req=urllib.request.Request(url=url,headers=headers)
html=urllib.request.urlopen(req).read()
html1=html.decode() #格式變得標准化。解碼
part1 = r'<div id="J_goodsList" .+?<div class="m-aside">'
result1 = re.compile(part1,flags=re.DOTALL).findall(html1)
result1=result1[0] #使數據變得工整而且格式化了 么以偶了/n等重復
part2=r'<img width="220" height="220" class="err-product" data-img="1" source-data-lazy-img="//(.+?\.jpg)" />'
imagelist=re.compile(part2).findall(result1)
x=1
for imageurl in imagelist:
imagename="D:/python_code/pachong/handle/jd_image/"+str(page)+str(x)+'.jpg'
imageurl='http://'+imageurl
try:
urllib.request.urlretrieve(imageurl,filename=imagename)
except urllib.error.URLError as e:
if hasattr(e,'code'):
x+=1
if hasattr(e,'reason'):
x+=1
x+=1
for i in range(1,5):
url='https://search.jd.com/Search?keyword=iphonex&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&suggest=1.his.0.0&page='+str(i)
crawl(url,i)
print('第i爬取成功')
今日頭條
import requests
import re
import json
from urllib.parse import urlencode
from requests.exceptions import RequestException
import pymongo
import os
from hashlib import md5
MONG_DB='toutiao'
MONG_TABLE='toutiao'
client=pymongo.MongoClient('127.0.0.1',27017)
db=client[MONG_DB]
def seve_mongo(result):
if db[MONG_TABLE].insert(result): #一定是[]
print('存蓄成功',result)
return True
return False
def get_index_page(offset,keyworld):
data={
'aid': '24',
'app_name': 'web_search',
'offset':offset,
'format': 'json',
'keyword': keyworld,
'autoload': 'true',
'count': '20',
'en_qc':'1',
'cur_tab':'1',
'from': 'search_tab',
'pd': 'synthesis',
}
headers={
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
}
cookies={
'cookie':'tt_webid=6691096928111166988; WEATHER_CITY=%E5%8C%97%E4%BA%AC; tt_webid=6691096928111166988; UM_distinctid=16ab99fb45d16e-04be26d83dc51d-6353160-144000-16ab99fb45e30f; csrftoken=3859f31127aece7bfebdd8efd257d464; s_v_web_id=dc502212a4a9466637eee610d6bd51b6; __tasessionId=jvaqvqe0u1557902021235; CNZZDATA1259612802=1956023403-1557890949-https%253A%252F%252Fcn.bing.com%252F%7C1557901749'
}
url='https://www.toutiao.com/api/search/content/?'+urlencode(data)
#它可以把字典類型轉換為url格式
response=requests.get(url,headers=headers,cookies=cookies)
try:
if response.status_code == 200:
return response.text
else:
None
except RequestException:
print('請求網頁出錯')
return None
def parse_page_index_url(html):
data=json.loads(html)
#json.load將字符串變成一個對象json
if data and 'data' in data.keys(): #data.keys返回的就是鍵名
for item in data.get('data'):
yield item.get('article_url') #yield 生成器,yield:可以看為return,但是返回的不是一個函數的輸出,是一個生成器的結果。當程序遇到yield后,停止執行並返回,當再次調用時,會在停止的地方繼續執行。一個方法用來yield,那么它就是一個生成器。
def get_page_detail(url):
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
}
cookies = {
'cookie': 'tt_webid=6691096928111166988; WEATHER_CITY=%E5%8C%97%E4%BA%AC; tt_webid=6691096928111166988; UM_distinctid=16ab99fb45d16e-04be26d83dc51d-6353160-144000-16ab99fb45e30f; csrftoken=3859f31127aece7bfebdd8efd257d464; s_v_web_id=dc502212a4a9466637eee610d6bd51b6; __tasessionId=jvaqvqe0u1557902021235; CNZZDATA1259612802=1956023403-1557890949-https%253A%252F%252Fcn.bing.com%252F%7C1557901749'
}
try:
response=requests.get(url,headers=headers,cookies=cookies)
if response.status_code == 200:
return response.text
else:
None
except RequestException:
print('請求詳情頁出錯',url)
return None
def get_page_detail_url(html_detail):
part=r'img src="(.*?)" img_width'
result=re.compile(part,flags=re.DOTALL).findall(str(html_detail))
part1 = r"title: '(.*?)'"
result1 = re.compile(part1, flags=re.DOTALL).findall(str(html_detail))
return {
'title':result1,
'url':result,
}
def get_page_detail_title(html_detail):
part=r"title: '(.*?)'"
result = re.compile(part, flags=re.DOTALL).findall(str(html_detail))
return result
def download_image(url):
print('當前正在下載',url)
try:
response = requests.get(url)
if response.status_code==200:
save_image(response.content)
return None
except RequestException:
print('請求圖片出錯',url)
return None
def save_image(content):
file_path='{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg')
if not os.path.exists(file_path):
with open(file_path,'wb')as f:
f.write(content)
f.close()
def main():
# a=input('請輸入頁面數:')
# b=input('請輸入關鍵字:')
# html=get_index_page(a,str(b))
html = get_index_page(0, '街拍')
for url in parse_page_index_url(html):
html_detail=get_page_detail(url)
result=get_page_detail_url(html_detail)
seve_mongo(result)
if __name__ == '__main__':
main()
貓眼電影
import requests
import re
from requests.exceptions import RequestException
def get_one_page(url):
try:
response = requests.get(url)
if response.status_code==200:
return response.text
return None
except RequestException:
return None
def parse_one_page(html):
pattern = re.compile(r'<dd>.*?<i class="board-index board-index-.*?">(\d+)</i>.*?<a href="(.*?)".*?title="(.*?)".*?<img data-src="(.*?)".*?<p class="star">(.*?)</p>.*?<p class="releasetime">(.*?)</p>.*?<i class="integer">(\d+)',flags=re.DOTALL)
# 這樣就不會出結果pattern = re.compile(r'<dd>.*?<i class="board-index board-index-.*?">(\d+)</i>.*?<a href="(.*?)".*?title="(.*?)".*?<img data-src="(.*?)".*?<p class="star">(.*?)</p>.*?<p class="releasetime">(.*?)</p>.*?<i class="integer">(\d+)</i>',flags=re.DOTALL)
items=re.findall(pattern,html)
print(items)
def main():
url='https://maoyan.com/board/4?offset=0'
html=get_one_page(url)
print(html)
parse_one_page(html)
if __name__=='__main__':
main()
美女圖
import requests
from lxml import etree
# 設計模式 --》面向對象編程
class Spider(object):
def __init__(self):
# 反反爬蟲措施,加請求頭部信息
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
"Referer": "https://www.mzitu.com/xinggan/"
}
def xpath_data(self, html):
# 2. 抽取想要的數據 標題 圖片 xpath
src_list = html.xpath('//ul[@id="pins"]/li/a/img/@data-original')
alt_list = html.xpath('//ul[@id="pins"]/li/a/img/@alt')
for src, alt in zip(src_list, alt_list):
file_name = alt + ".jpg"
response = requests.get(src, headers=self.headers)
# 3. 存儲數據 jpg with open
try:
with open('D:/Python_code/pachong/handle/mzitu/'+file_name, "wb") as f:
f.write(response.content)
print("正在抓取圖片:" + file_name)
except:
print("==========文件名有誤!==========")
def start_request(self):
# 1. 獲取整體網頁的數據 requests
for i in range(1, 5):
print("==========正在抓取%s頁==========" % i)
response = requests.get("https://www.mzitu.com/page/" + str(i) + "/", headers=self.headers)
html = etree.HTML(response.content.decode())
self.xpath_data(html)
spider = Spider()
spider.start_request()
淘寶
from selenium import webdriver
import requests
#下面三個復制python selenium的wait
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser =webdriver.Chrome()
def search():
try:
browser.get('https://www.taobao.com')
# 以下代碼也是復制過來,將driver改為browser等改動都在頁面有
# 而(By.CSS_SELECTOR, "#q")這個則是直接在淘寶網頁選擇該元素,然后點擊copy,copy selector就是他們了如搜索是#q,點擊是#J_TSearchForm > div.search-button > button
# element = WebDriverWait(driver, 10).until(
# EC.presence_of_element_located((By.ID, "myDynamicElement"))
input = WebDriverWait(browser, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#q"))
)
submit=WebDriverWait(browser, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR,"#J_TSearchForm > div.search-button > button"))
)
#下面就是模擬操作了,也在頁面里面有如send_keys就在7.2中
input.send_keys('美食')
submit.click()
total=WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#J_relative > div.sort-row > div > div.pager > ul > li:nth-child(2)")))
return total.text
except TimeoutError:
return search()
def main():
total=search()
if __name__=='__main__':
main()
貼吧
import requests
import threading
from bs4 import BeautifulSoup
import re
from lxml import etree
class tieba(object):
#1初始化,傳參作用等
def __init__(self,query_string):
self.query_string=query_string
self.url='https://tieba.baidu.com/f'
self.headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'}
#2
def parse_data(self,data,rule):
html_data=etree.HTML(data)
data_list=html_data.xpath(rule)
return data_list
#3
def seve_data(self,data,name):
path='D:/Python_code/pachong/handle/tieba/'+name
with open (path,'wb') as f:
f.write(data)
print("%s爬取完成" %name )
#4
def params(self):
para={
'kw':self.query_string
}
return para
def send_request(self,url,parms={}):
response=requests.get(url,params=parms,headers=self.headers)
return response.content
def run(self):
tieba_params=self.params()
datas=self.send_request(self.url,tieba_params)
#re
html=datas.decode()
url_list=re.compile('<a rel="noreferrer" href="(.+)" title.*?</a>').findall(html)
# xpath
# detail_rule="//div[@class='t_con cleafix']/div/div/div/a/@href"
# url_list=self.parse_data(datas,detail_rule)
for url in url_list:
detail_url='https://tieba.baidu.com'+url
detail_data=self.send_request(detail_url)
image_url='//img[@class="BDE_Image"]/@src'
image_url_list=self.parse_data(detail_data,image_url)
for image_url_1 in image_url_list:
image_data=self.send_request(image_url_1)
image_name=image_url_1[-12:]
self.seve_data(image_data,image_name)
if __name__ == '__main__':
a=input('請輸入你要的關鍵字')
tieba=tieba(a)
tieba.run()
vip電影
import tkinter
import tkinter.messagebox
import webbrowser
def Button():
a = 'http://www.82190555.com/video.php?url=' if varRadio.get() else 'http://jx.598110.com/?url='
b = entry_movie_link.get()
webbrowser.open(a+b)
def qk():
entry_movie_link.delete(0,'end')
def openaqy():
webbrowser.open('http://www.iqiyi.com')
def opentx():
webbrowser.open('http://v.qq.com')
def openyq():
webbrowser.open('http://www.youku.com/')
def about():
abc='''
經過測試愛奇藝、優酷、騰訊的VIP視頻可以播放
鏈接格式為
http://www.iqiyi.com/v_19rrb2u62s.html?fc=82992814760eeac6
通道 可能由於變換沒法播出時請切換通道
'''
tkinter.messagebox.showinfo(title='幫助文件', message=abc)
def zzxx():
msg='''
yj 666
'''
tkinter.messagebox.showinfo(title='聯系方式', message=msg)
if __name__ == '__main__':
root=tkinter.Tk()
root.title('yj666')
root['width']=500
root['height']=300
menubar = tkinter.Menu(root)
helpmenu = tkinter.Menu(menubar, tearoff=0)
helpmenu.add_command(label='幫助文檔', command=about)
helpmenu.add_command(label='作者信息', command=zzxx)
menubar.add_cascade(label='幫助(H)', menu=helpmenu)
root.config(menu=menubar)
varentry1= tkinter.StringVar(value='')
lab_movie_gallery=tkinter.Label(root, text='視頻播放通道')
lab_movie_gallery.place(x=20,y=20,width=100,height=20)
varRadio=tkinter.IntVar(value=1)
Radiobutton1_movie_gallery=tkinter.Radiobutton(root,variable=varRadio,value=0,text='視頻通道1')
Radiobutton2_movie_gallery = tkinter.Radiobutton(root, variable=varRadio, value=1, text='視頻通道2')
Radiobutton1_movie_gallery.place(x=130,y=20,width=100,height=20)
Radiobutton2_movie_gallery.place(x=250, y=20, width=100, height=20)
varentry2=tkinter.StringVar(value='https://v.qq.com/x/cover/1o29ui77e85grdr/h0022ah1yrf.html')
lab_movie_link = tkinter.Label(root, text='視頻播放鏈接')
lab_movie_link.place(x=20, y=60, width=100, height=20)
entry_movie_link = tkinter.Entry(root, textvariable=varentry2)
entry_movie_link.place(x=130, y=60, width=300, height=20)
button_movie_link=tkinter.Button(root,text='清空',command=qk)
button_movie_link.place(x=440,y=60,width=30,height=20)
lab_remind = tkinter.Label(root, text='將視頻鏈接復制到框內,點擊播放VIP視頻')
lab_remind.place(x=50, y=90, width=400, height=20)
varbutton=tkinter.StringVar
button_movie= tkinter.Button(root, text='播放VIP視頻', command=Button)
button_movie.place(x=140, y=120, width=200, height=60)
button_movie1 = tkinter.Button(root, text='愛奇藝', command=openaqy)
button_movie1.place(x=60, y=200, width=100, height=60)
button_movie2 = tkinter.Button(root, text='騰訊視頻', command=opentx)
button_movie2.place(x=180, y=200, width=100, height=60)
button_movie3 = tkinter.Button(root, text='優酷視頻', command=openyq)
button_movie3.place(x=300, y=200, width=100, height=60)
root.mainloop()
知乎
import requests
class Get_follow(object):
def __init__(self,page):
self.page=page
self.url='https://www.zhihu.com/api/v4/members/mwycegusa/followers?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset={}&limit=20'.format(page*20)
self.headers={
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
}
self.cookie={
'cookie':'_zap=02f27f98-87e4-43fd-a3c4-288621b56d09; d_c0="AMDlavhINg-PTn2F7IvBkJzHDhu7npy4o3k=|1554121045"; __gads=ID=057bb41b2faa002c:T=1554121053:S=ALNI_MYvPXKcplL1UDWgkALfG5CcunCbFQ; q_c1=04444d44ef5a4b87a6a22e9ed3ae687f|1557222293000|1554121051000; r_cap_id="ZmZmMjAyMDhkOTI2NGQ4ZmFkZTRmMjk2MWY5MjJjYjM=|1557222293|f0b285636da386a5a9425d18c252ac7019f22478"; cap_id="NTE2M2Y5Yjg0MDMxNDU0MmEyNTI5NGY4Mzk2MTU3MTA=|1557222293|06f8e2466a62fd12e4c0455bb190ca45b4aa7673"; l_cap_id="YzAwMGMyMzYyZTZiNDc4OWE4MGY5MzA1ODA4ODI4OTA=|1557222293|2b8fbb964c0596b102fe6c5385f52c8b49354717"; __utma=51854390.922669224.1557222296.1557222296.1557222296.1; __utmz=51854390.1557222296.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=51854390.000--|3=entry_date=20190401=1; _xsrf=4LK6GhKpu3XhmKHkcAeQLS36FeuumzHq; capsion_ticket="2|1:0|10:1557642571|14:capsion_ticket|44:NjI5MzEwNDEzNGNjNGE2NGI4NGY4ZDczYTM2YjU5YjY=|28b611d285b2b29acb7f11f50c21b9d2333df95e3831b408ca5a2e750f86582a"; z_c0="2|1:0|10:1557642658|4:z_c0|92:Mi4xaUYwUkNRQUFBQUFBd09WcS1FZzJEeVlBQUFCZ0FsVk5vZ3ZGWFFCUFNsUzNpWkVjdFpKVDQ5NmpEOWxYT1pmQmVn|722efca13331bcfc016ea98db395ec0f59dbdde75b51285f0099f847fa794e21"; tst=f; tgw_l7_route=66cb16bc7f45da64562a077714739c11'
}
def get_html(self):
response=requests.get(self.url,headers=self.headers,cookies=self.cookie)
# data= response.json()['data']
# print(data)
list=[]
for item in response.json()['data']:
list.append(item['id'])
print(list)
class Send_MSG(object):
def __init__(self):
self.url='https://www.zhihu.com/api/v4/messages'
self.headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
}
self.data={
'content': "本條內容由Python 腳本發送,如果可以,請關注我,謝謝,打擾打擾",
'created_time': '1557720982',
'has_read': 'false',
'id': '1111243022582411264'
}
def Send(self):
try:
requests.post(self.url,json=self.data,headers=self.headers)
print('發送成功')
except:
print('發送失敗')
if __name__ == '__main__':
page=input('請輸入該用戶粉絲頁面數:')
for i in range(int(page)):
a=Get_follow(i)
a.get_html()
msg_send=Send_MSG()
msg_send.Send()
