上網(wǎng)原理
1涧团、爬蟲概念
爬蟲是什麼只磷?
蜘蛛,蛆泌绣,代碼中钮追,就是寫了一段代碼,代碼的功能從互聯(lián)網(wǎng)中提取數(shù)據(jù)
互聯(lián)網(wǎng):
節(jié)點(diǎn)就是url(統(tǒng)一資源定位符)阿迈,有很多a鏈接組成
互聯(lián)網(wǎng)爬蟲:
寫代碼畏陕,模擬瀏覽器訪問url,并且從里面提取指定的內(nèi)容
都有哪些語言可以實(shí)現(xiàn)爬蟲仿滔?
1.php惠毁。號(hào)稱世界上最優(yōu)美的語言,php天生對(duì)多進(jìn)程多線程支持的不好
2.java崎页。是python最主要的競(jìng)爭(zhēng)對(duì)手鞠绰,也說它不好,java語言比較臃腫飒焦,重構(gòu)起來難度太大
3.c蜈膨,c++。也能夠?qū)崿F(xiàn)牺荠,不是最好的選擇翁巍,只能說是能力的體現(xiàn)
4.python,號(hào)稱世界上最美麗的語言休雌,代碼簡(jiǎn)潔灶壶,學(xué)習(xí)成本低,支持的模塊多杈曲,scrapy爬蟲框架
通用爬蟲
百度驰凛、360胸懈、搜狗、谷歌恰响、必應(yīng)等趣钱,搜索引擎
(1)從互聯(lián)網(wǎng)上抓取所有的數(shù)據(jù)
(2)對(duì)數(shù)據(jù)進(jìn)行處理
(3)對(duì)用戶提供檢索服務(wù)
百度如何爬取新的內(nèi)容?
(1)主動(dòng)的將域名提交給百度
(2)在其他網(wǎng)站中設(shè)置友情鏈接
(3)自己會(huì)和dns服務(wù)商進(jìn)行合作
robots協(xié)議:
就是一個(gè)君子協(xié)議胚宦,淘寶就不允許百度抓取
這個(gè)協(xié)議就是一個(gè)文件首有,要放到網(wǎng)站的根目錄
咱寫的爬蟲程序,你就不用遵從了
排名:
(1)根據(jù)一個(gè)值排名枢劝,pagerank绞灼,(seo)
(2)競(jìng)價(jià)排名库北,為浙西事件
缺點(diǎn):
(1)抓取的很多數(shù)據(jù)都是沒用的
(2)不能根據(jù)需求進(jìn)行爬取
聚焦爬蟲
根據(jù)自己的需求印蓖,提取指定的數(shù)據(jù)
我們學(xué)習(xí)的就是聚焦爬蟲
如何實(shí)現(xiàn)抓取指定的數(shù)據(jù):
(1)每一個(gè)網(wǎng)頁都有自己的唯一的url
(2)網(wǎng)頁都是由html組成的
(3)網(wǎng)頁的傳輸使用的都是http、https協(xié)議爬蟲的思路:
(1)要爬取的網(wǎng)頁的url
(2)寫代碼模擬瀏覽器發(fā)送http請(qǐng)求
(3)解析網(wǎng)頁內(nèi)容曹仗,字符串處理被冒,根據(jù)規(guī)則提取數(shù)據(jù)
開發(fā)環(huán)境
windows军掂、linux都可以
python 3.x 64位
編輯工具:pycharm sublime
整體內(nèi)容介紹:
(1)模擬瀏覽器發(fā)送請(qǐng)求
urllib.request urllib.parse requests
(2)解析內(nèi)容
正則表達(dá)式、bs4昨悼、xpath蝗锥、jsonpath
(3)動(dòng)態(tài)html
selenium+phantomjs
(4)scrapy框架的學(xué)習(xí)
(5)scrapy-redis的組件
(6)涉及到的爬蟲-反爬蟲-反反爬蟲的內(nèi)容
User-Agent、代理率触、驗(yàn)證碼终议、動(dòng)態(tài)數(shù)據(jù)
最終:理論上,只要瀏覽器能夠訪問的數(shù)據(jù)葱蝗,你的程序就能訪問
模擬登錄
2穴张、http協(xié)議
上網(wǎng)原理:看圖形
http和https的區(qū)別:
-
https://www.cnblogs.com/wqhwe/p/5407468.html
**
1、https協(xié)議需要到ca申請(qǐng)證書两曼,一般免費(fèi)證書較少皂甘,因而需要一定費(fèi)用。
2悼凑、http是超文本傳輸協(xié)議偿枕,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議户辫。
3渐夸、http和https使用的是完全不同的連接方式,用的端口也不一樣渔欢,前者是80墓塌,后者是443。
4、http的連接很簡(jiǎn)單桃纯,是無狀態(tài)的酷誓;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸披坏、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議态坦,比http協(xié)議安全。
http協(xié)議 https://www.cnblogs.com/10158wsj/p/6762848.html
一個(gè)完整的url
http://www.baidu.com:80/index.html?username=goudan&password=123456&lala=xixi#dudu
協(xié)議 域名 端口號(hào) 請(qǐng)求的資源 get參數(shù) 錨點(diǎn)
錨點(diǎn):可以實(shí)現(xiàn)同一個(gè)頁面的跳轉(zhuǎn)
請(qǐng)求:
請(qǐng)求行棒拂、請(qǐng)求頭伞梯、空行
常見請(qǐng)求頭
accept:瀏覽器通過這個(gè)頭告訴服務(wù)器,它所支持的數(shù)據(jù)類型
Accept-Charset: 瀏覽器通過這個(gè)頭告訴服務(wù)器帚屉,它支持哪種字符集
Accept-Encoding:瀏覽器通過這個(gè)頭告訴服務(wù)器谜诫,支持的壓縮格式(重要)
Accept-Language:瀏覽器通過這個(gè)頭告訴服務(wù)器,它的語言環(huán)境
Host:瀏覽器通過這個(gè)頭告訴服務(wù)器攻旦,想訪問哪臺(tái)主機(jī)
If-Modified-Since: 瀏覽器通過這個(gè)頭告訴服務(wù)器喻旷,緩存數(shù)據(jù)的時(shí)間
Referer:瀏覽器通過這個(gè)頭告訴服務(wù)器,客戶機(jī)是哪個(gè)頁面來的 防盜鏈(重要)
Connection:瀏覽器通過這個(gè)頭告訴服務(wù)器牢屋,請(qǐng)求完后是斷開鏈接還是何持鏈接
User-Agent:客戶端的類型
cookie:和身份有關(guān)的
響應(yīng):狀態(tài)行且预、響應(yīng)頭、實(shí)體內(nèi)容
常見響應(yīng)頭
Location: 服務(wù)器通過這個(gè)頭烙无,來告訴瀏覽器跳到哪里
Server:服務(wù)器通過這個(gè)頭锋谐,告訴瀏覽器服務(wù)器的型號(hào)
Content-Encoding:服務(wù)器通過這個(gè)頭,告訴瀏覽器截酷,數(shù)據(jù)的壓縮格式
Content-Length: 服務(wù)器通過這個(gè)頭涮拗,告訴瀏覽器回送數(shù)據(jù)的長(zhǎng)度
Content-Language: 服務(wù)器通過這個(gè)頭,告訴瀏覽器語言環(huán)境
Content-Type:服務(wù)器通過這個(gè)頭迂苛,告訴瀏覽器回送數(shù)據(jù)的類型
Refresh:服務(wù)器通過這個(gè)頭三热,告訴瀏覽器定時(shí)刷新
Content-Disposition: 服務(wù)器通過這個(gè)頭,告訴瀏覽器以下載方式打數(shù)據(jù)
Transfer-Encoding:服務(wù)器通過這個(gè)頭三幻,告訴瀏覽器數(shù)據(jù)是以分塊方式回送的
**Expires: -1 **控制瀏覽器不要緩存
Cache-Control: no-cache
Pragma: no-cache
3康铭、抓包工具
sublime安裝和使用
- (1)安裝插件管理器,packagecontrol
- (2)安裝插件
按:ctrl + shift + p
輸入pci赌髓,點(diǎn)擊installpackage即可
搜索想要安裝的插件从藤,敲enter即可安裝 - (3)卸載插件
按:ctrl + shift + p
輸入remove,選中remove package即可
抓包:
谷歌瀏覽器自帶抓包工具
network锁蠕,點(diǎn)擊看詳情
response.headers 響應(yīng)頭部
request.headers 請(qǐng)求頭
query_string 請(qǐng)求字符串夷野,get參數(shù)
formadata 請(qǐng)求參數(shù),post參數(shù)
response:響應(yīng)內(nèi)容
fiddler軟件
專業(yè)的抓包軟件
配置:
正常步驟:options==》https==》capture https connects==>action==>trust root certificate
windows有問題:https://blog.csdn.net/d1240673769/article/details/74298429/ubuntu下配置 http://fiddler.wikidot.com/mono
配置完畢荣倾,重啟fiddler即可
如何使用
見文檔
4悯搔、urllib庫
是干什么的?是python用來模擬http發(fā)送請(qǐng)求的舌仍,是python自帶的一個(gè)模塊
python2.x :urllib妒貌,urllib2
python3.x :urllib
urllib.request : 發(fā)送請(qǐng)求通危、獲取響應(yīng)
urlopen(url=xxx, data=xxx) : 發(fā)送get,直接將參數(shù)拼接到url的后面灌曙,發(fā)送post菊碟,就需要data參數(shù)了
response對(duì)象:
read() :
讀取的為二進(jìn)制數(shù)據(jù)
字符串類型《====》二進(jìn)制類型
encode() :
字符串格式轉(zhuǎn)化為二進(jìn)制格式,不寫代表utf8在刺,寫gbk就代表gbk
decode() :
二進(jìn)制轉(zhuǎn)為字符串逆害,不寫就是utf8,寫gbk就是gbk
readlines() :
讀取為列表格式蚣驼,按行讀取
getcode() :
獲取狀態(tài)碼
geturl() :
獲取請(qǐng)求的url
getheaders() :
返回響應(yīng)頭部魄幕,列表里面有元組
urlretrieve() :
發(fā)送請(qǐng)求,并且將響應(yīng)信息直接寫入到文件中
urllib.parse :
用來處理數(shù)據(jù)
quote() :
對(duì)url里面的非法字符進(jìn)行編碼颖杏,字母纯陨、數(shù)字、下劃線留储、&翼抠、://
unquote() :
url解碼
urlencode() :
傳遞一個(gè)字典,將字典轉(zhuǎn)化為
query_stirng ,
并且里面的非法字符得到編碼
5欲鹏、構(gòu)建請(qǐng)求對(duì)象
User-Agent : 客戶端瀏覽器類型
定制請(qǐng)求頭部机久,將自己偽裝成pc瀏覽器
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
# 構(gòu)建請(qǐng)求對(duì)象
request = urllib.request.Request(url=url, headers=headers)
fiddler使用文檔
1、配置
2赔嚎、使用
左邊:所有的請(qǐng)求
<> : 返回的是html文檔
圖片標(biāo)記:代表是圖片
{json} : 返回json格式
{css} : css文件
js: js文件
右邊:查看某個(gè)請(qǐng)求的詳細(xì)信息
inspectors
右上:這個(gè)請(qǐng)求所有的請(qǐng)求信息
raw:請(qǐng)求的原始信息
webforms:請(qǐng)求所帶參數(shù)膘盖,
query_string代表get參數(shù),formdata代
表post參數(shù)
右下:所有的響應(yīng)信息
raw:查看詳細(xì)的響應(yīng)信息
json:如果返回的是json數(shù)據(jù)尤误,在這里
查看
清除所有請(qǐng)求
removeall 清除所有請(qǐng)求
file==》capture 關(guān)閉或者啟動(dòng)抓包
快捷鍵:
select html : 所有的html請(qǐng)求
select js : 所有的js請(qǐng)求
?baidu : 選中所有帶有baidu的請(qǐng)求
cls : 清除所有的請(qǐng)求
地址編碼
import urllib.parse
# url = 'http://www.baidu.com/index.html?name=狗蛋'
# str1 = urllib.parse.quote(url)
url = 'http://www.baidu.com/index.html?'
data = {
'username':'狗蛋',
'pwd':'jsjsjs',
'height':'175',
}
string1 = urllib.parse.urlencode(data)
print(string1)
url+=string1
print(url)
圖片保存
#
import urllib.request
url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1531147620161&di=cc9bfc90e915669e609905a13b01affd&imgtype=0&src=http%3A%2F%2Fnres.ingdan.com%2Fuploads%2F20151210%2F1449737241395228.jpg'
response = urllib.request.urlopen(url)
urllib.request.urlretrieve(url,'tu.jpg')
網(wǎng)頁文件down
import urllib.request
url = 'http://www.sougou.com/'
response = urllib.request.urlopen(url)
with open('sougouq.html','w',encoding='utf-8') as fp:
fp.write(response.read().decode())
print(response.getcode())
post請(qǐng)求
#百度翻譯初級(jí)入門
import urllib.request
import urllib.parse
post_url = 'http://fanyi.baidu.com/v2transapi'
#data
# word = input('請(qǐng)輸入')
word = 'river'
formdata = {
'from': 'en',
'to':'zh',
'query': word,
'transtype': 'realtime',
'simple_means_flag': '3',
'sign': '555962.825483',
'token': '8d393681119b809e14f9636ea55337c5',
}
formdata = urllib.parse.urlencode(formdata).encode('utf8')
headers = {
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Content-Length': '123',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': 'BAIDUID=9AB6C0FBB652B8E5C0EB2116B4794D8A:FG=1; BIDUPSID=9AB6C0FBB652B8E5C0EB2116B4794D8A; PSTM=1519631202; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BDUSS=DJsdjlXaDlrZm5TUjdkY0NjSU05SWdaM2dxYlh4dFpwcXlQWnJtVFFSa2JKUnBiQUFBQUFBJCQAAAAAAAAAAAEAAAC8V7VPdGltZbXEcml2ZXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuY8lobmPJaW; H_PS_PSSID=26522_1458_21108_18560_22073; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; PSINO=2; locale=zh; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1531202878,1531203779,1531203784; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1531203784',
'Host': 'fanyi.baidu.com',
'Origin': 'http://fanyi.baidu.com',
'Referer': 'http://fanyi.baidu.com/?aldtype=16047',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'
}
#構(gòu)建請(qǐng)求對(duì)象
# request = urllib.request.Request(url=post_url,headers=headers)
# #獲取相應(yīng)
# resposne = urllib.request.urlopen(request,data=formdata)
# print(resposne.read().decode('utf8'))
request = urllib.request.Request(url=post_url,headers=headers)
response = urllib.request.urlopen(request,data=formdata)
print(response.read().decode('utf8'))
get請(qǐng)求
import urllib.request
import urllib.parse
url = 'https://www.baidu.com/s?'
# word = input('請(qǐng)輸入')
word = '煙臺(tái)'
data = {
'ie':'utf8',
'wd':word
}
quit_string = urllib.parse.urlencode(data)
url+=quit_string
headers = {
'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36'
}
request = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
with open( '{}.html'.format(word),'w',encoding='utf-8') as fp:
fp.write(response.read().decode('utf8'))
ajax get請(qǐng)求
# ajax-get
import urllib.request
import urllib.parse
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'
print('每頁顯示二十條數(shù)據(jù)')
# page = input('請(qǐng)輸入你要幾頁的數(shù)據(jù)')
page = 4
start = (page-1)*20
limit = 20
data = {
'start':start,
'limit':limit,
}
qury_string = urllib.parse.urlencode(data)
url +=qury_string
headers = {
'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36'
}
request = urllib.request.Request(url = url,headers=headers)
response = urllib.request.urlopen(request)
print(response.read().decode('utf8'))
ajax post 請(qǐng)求
# ajax-post
# kfc
import urllib.request
import urllib.parse
post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
data = {
'cname':'北京',
'pageIndex':'1',
'pid':'',
'pageSize':'10',
}
data = urllib.parse.urlencode(data).encode('utf8')
headers = {
'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36'
}
request = urllib.request.Request(url=post_url,headers=headers)
resposne = urllib.request.urlopen(request,data=data)
print(resposne.read().decode('utf8'))
爬蟲2
1模擬各種請(qǐng)求方式
get請(qǐng)求
import urllib.request
import urllib.parse
url = 'https://www.baidu.com/s?'
word = input('請(qǐng)輸入要查詢的內(nèi)容:')
# get參數(shù)寫到這里
data = {
'ie': 'utf8',
'wd': word,
}
# 拼接url
query_string = urllib.parse.urlencode(data)
url += query_string
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
# 構(gòu)建請(qǐng)求對(duì)象
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
filename = word + '.html'
# 寫入到文件中
with open(filename, 'wb') as fp:
fp.write(response.read())
# 插件侠畔,sublime-repl
post請(qǐng)求
- 百度翻譯 XMLHttpRequest
import urllib.request
import urllib.parse
post_url = 'http://fanyi.baidu.com/sug'
# word = input('請(qǐng)輸入要查詢的英文單詞:')
word = 'baby'
# post攜帶的參數(shù)
data = {
'kw': word
}
# 對(duì)post參數(shù)進(jìn)行處理
data = urllib.parse.urlencode(data).encode('utf8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
# 構(gòu)建請(qǐng)求對(duì)象
request = urllib.request.Request(url=post_url, headers=headers)
# 發(fā)送請(qǐng)求
response = urllib.request.urlopen(request, data=data)
print(response.read().decode('utf8'))
進(jìn)階
import urllib.request
import urllib.parse
post_url = 'http://fanyi.baidu.com/v2transapi'
# post參數(shù)
formdata = {
'from': 'en',
'to': 'zh',
'query': 'baby',
'transtype': 'realtime',
'simple_means_flag': '3',
'sign': '814534.560887',
'token': '921cc5d0819e0f1b4212c7fdc3b23866',
}
# 處理表單數(shù)據(jù)
formdata = urllib.parse.urlencode(formdata).encode('utf8')
headers = {
'Accept': '*/*',
# 'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
# 'Content-Length': '121',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': 'BAIDUID=59CCBF5477FDC81799054A3DA85BEF88:FG=1; BIDUPSID=59CCBF5477FDC81799054A3DA85BEF88; PSTM=1529815427; pgv_pvi=2975680512; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; locale=zh; to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; H_PS_PSSID=1436_26432_21094_20929; PSINO=2; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1531189205,1531202737; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1531202737',
'Host': 'fanyi.baidu.com',
'Origin': 'http://fanyi.baidu.com',
'Referer': 'http://fanyi.baidu.com/?aldtype=16047',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
}
# 構(gòu)建請(qǐng)求對(duì)象,發(fā)送請(qǐng)求
request = urllib.request.Request(url=post_url, headers=headers)
# 發(fā)送請(qǐng)求
response = urllib.request.urlopen(request, data=formdata)
print(response.read().decode('utf-8'))
ajax-get請(qǐng)求
- 豆瓣電影排行榜
DOM BOM
https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20
start = 20 limit = 20
start = 40 limit = 20
第n頁 start = (n-1)*20 limit = 20
import urllib.request
import urllib.parse
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'
print('每頁顯示20條數(shù)據(jù)')
# page = input('請(qǐng)輸入要第幾頁數(shù)據(jù):')
page = 3
# 根據(jù)page就可以計(jì)算出來start和limit的值
start = (page-1) * 20
limit = 20
# 寫get參數(shù)
data = {
'start': start,
'limit': limit,
}
# 將字典轉(zhuǎn)化為query_string格式
query_string = urllib.parse.urlencode(data)
# 拼接url
url += query_string
# print(url)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
print(response.read().decode('utf8'))
ajax-post請(qǐng)求
- 肯德基店鋪位置
import urllib.request
import urllib.parse
post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
data = {
'cname': '石河子',
'pid': '',
'pageIndex': '1',
'pageSize': '10',
}
# 處理data數(shù)據(jù)
data = urllib.parse.urlencode(data).encode('utf8')
#
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=post_url, headers=headers)
response = urllib.request.urlopen(request, data=data)
print(response.read().decode())
2损晤、復(fù)雜get
百度貼吧
-
https://tieba.baidu.com/f?kw=%E6%9D%8E%E6%AF%85&ie=utf-8&pn=0
第一頁 pn=0
第二頁 pn=50
第三頁 pn=100
第n頁 pn=(n-1)*50
輸入吧名软棺,輸入要爬取的起始頁碼,輸入要爬取的結(jié)束頁碼
在當(dāng)前創(chuàng)建一個(gè)文件夾尤勋,文件夾名字就是吧名喘落,在吧名文件夾里面,有好多文件最冰,就每一頁的內(nèi)容瘦棋,第1頁.html 第2頁.html xxxx
import urllib.request
import urllib.parse
import os
import time
def handle_request(url, baname, page):
pn = (page-1) * 50
# 拼接url
data = {
'ie': 'utf8',
'kw': baname,
'pn': pn,
}
query_string = urllib.parse.urlencode(data)
url += query_string
# print(url)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
return request
# 根據(jù)請(qǐng)求對(duì)象,下載指定的響應(yīng)內(nèi)容到本地
def download(request, baname, page):
# 根據(jù)吧名暖哨,創(chuàng)建文件夾的過程
# 判斷文件夾是否存在赌朋,不存在才創(chuàng)建
if not os.path.exists(baname):
os.mkdir(baname)
# 文件的名字
filename = '第%s頁.html' % page
print('正在下載%s......' % filename)
# 拼接文件的全路徑
filepath = os.path.join(baname, filename)
response = urllib.request.urlopen(request)
# 將內(nèi)容都進(jìn)來
content = response.read()
# 將內(nèi)容寫入到文件中
with open(filepath, 'wb') as fp:
fp.write(content)
print('結(jié)束下載%s' % filename)
def main():
url = 'https://tieba.baidu.com/f?'
# 要爬取的貼吧的名字
baname = input('請(qǐng)輸入要爬取的吧名:')
# 起始頁碼、結(jié)束頁碼
start_page = int(input('請(qǐng)輸入起始頁碼:'))
end_page = int(input('請(qǐng)輸入結(jié)束頁碼:'))
# 搞個(gè)循環(huán)
for page in range(start_page, end_page + 1):
# 根據(jù)不同的page生成不同哦url,然后生成不同的請(qǐng)求
request = handle_request(url, baname, page)
# 發(fā)送請(qǐng)求沛慢,獲取響應(yīng)
download(request, baname, page)
# 停頓一下
time.sleep(2)
if __name__ == '__main__':
main()
3赡若、URLError\HTTPError
異常處理,NameError, 這兩個(gè)異常在urllib.error里面
URLError:不存在的域名团甲,電腦沒有聯(lián)網(wǎng)
www.goudan.comHTTPError: 404找不到頁面
HTTPError是URLError的子類,如果多個(gè)except在進(jìn)行捕獲逾冬,HTTPError要寫到前面
import urllib.request
import urllib.error
'''
url = 'http://www.maodan.com/'
try:
response = urllib.request.urlopen(url)
except Exception as e:
print(e)
'''
url = 'https://blog.csdn.net/hudeyu777/article/details/76021574'
try:
response = urllib.request.urlopen(url)
except urllib.error.HTTPError as e:
print(e)
except urllib.error.URLError as e:
print(e)
4、Handler處理器伐庭、自定義Opener
是什麼意思呢粉渠?
++++引入請(qǐng)求對(duì)象為了定制頭部
更高級(jí)的功能就要使用handler和opener分冈,步驟都是首先創(chuàng)建一個(gè)handler圾另,然后創(chuàng)建一個(gè)opener,然后通過opener的open方法來發(fā)送請(qǐng)求
通過handler和opener實(shí)現(xiàn)最基本的請(qǐng)求
import urllib.request
url = 'http://www.baidu.com/'
# 創(chuàng)建一個(gè)handler
handler = urllib.request.HTTPHandler()
# 根據(jù)handler來創(chuàng)建一個(gè)opener
opener = urllib.request.build_opener(handler)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
# 再往下發(fā)送請(qǐng)求操作雕沉,都通過opener的open方法集乔,沒有urlopen()這個(gè)方法了
response = opener.open(request)
print(response.read().decode('utf8'))
5、代理
- 代理:代駕坡椒,代購扰路,代練
我們的代理
代理服務(wù)器:
--------------------西祠代理
--------------------快代理
- 瀏覽器配置代理
101.236.21.22:8866
程序配置代理
import urllib.request
url = 'http://www.baidu.com/s?ie=UTF-8&wd=ip'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url, headers=headers)
# 101.236.21.22:8866
# 使用代理訪問
handler = urllib.request.ProxyHandler(proxies={'http': '101.236.21.22:8866'})
# 根據(jù)handler創(chuàng)建opener
opener = urllib.request.build_opener(handler)
response = opener.open(request)
with open('daili.html', 'wb') as fp:
fp.write(response.read())
6、cookie
cookie是什麼倔叼?會(huì)員卡
為什么引入cookie汗唱?http有一個(gè)特點(diǎn),無狀態(tài)
每次的請(qǐng)求和響應(yīng)都是獨(dú)立的丈攒,沒有什么關(guān)系
缺點(diǎn)哩罪?
兩次請(qǐng)求如果有聯(lián)系,服務(wù)端識(shí)別不出來
要想識(shí)別出來巡验,引入了cookie
day03-爬蟲3
1际插、cookie
常用在模擬登錄中
通過代碼如何訪問登錄后的頁面?
http://www.renren.com/960481378/profile
- (1)偽造cookie显设,進(jìn)行訪問
- (2)模擬瀏覽器的方式框弛,首先發(fā)送post,先登錄成功捕捂,然后發(fā)送get瑟枫,訪問登錄后的頁面
ps:fiddler上面,一個(gè)本上面有個(gè)箭頭指攒,這個(gè)就是post請(qǐng)求
import urllib.request
import urllib.parse
# 直接訪問這個(gè)頁面慷妙,肯定是不行的,需要偽造cookie
url = 'http://www.renren.com/960481378/profile'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
with open('renren.html', 'wb') as fp:
fp.write(response.read())
# 通過抓包幽七,抓取瀏覽器訪問時(shí)候的cookie景殷,通過代碼模擬發(fā)送即可
url = 'http://www.renren.com/960481378/profile'
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Cookie': 'anonymid=jjgfrq7uasf0qc; depovince=GW; jebecookies=49de5f46-0b80-490f-9277-f19688fc91a3|||||; _r01_=1; JSESSIONID=abcYl2ngsw4FBhTX16gsw; ick_login=52175eb0-6f30-4f87-b614-91fa81350f73; _de=F872F5698F7602B30ADE65415FC01940; p=42e7d8c2c4c06f39f70b2be38468f15f8; first_login_flag=1; ln_uact=17701256561; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; t=d34342f75a43ffa1c061400e9126ea118; societyguester=d34342f75a43ffa1c061400e9126ea118; id=960481378; xnsid=79143e47; ver=7.0; loginfrom=null; wp_fold=0; jebe_key=2f649712-9cf8-44a8-8c6a-145cfab423ae%7C86ba94a3b75a9848502e25ac92562959%7C1531272254868%7C1',
'Host': 'www.renren.com',
'Referer': 'http://www.renren.com/960481378/profile',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
with open('renren.html', 'wb') as fp:
fp.write(response.read())
模擬登陸人人網(wǎng)獲取登陸后的界面
import urllib.request
import urllib.parse
import http.cookiejar
# 高級(jí)請(qǐng)求cookie的代碼實(shí)現(xiàn)
# 這個(gè)ck對(duì)象可以保存cookie
ck = http.cookiejar.CookieJar()
# 根據(jù)ck對(duì)象創(chuàng)建一個(gè)handler
handler = urllib.request.HTTPCookieProcessor(ck)
# 根據(jù)handler創(chuàng)建一個(gè)opener
opener = urllib.request.build_opener(handler)
# 往下所有的請(qǐng)求都使用opener.open()方法進(jìn)行發(fā)送,這樣就會(huì)和瀏覽器的功能一模一樣,就是保存cookie并且自動(dòng)攜帶cookie發(fā)送請(qǐng)求的功能
# 抓包獲取到post_url
post_url = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=201863950868'
# 表單數(shù)據(jù)
data = {
'email': '17701256561',
'icode': '',
'origURL': 'http://www.renren.com/home',
'domain': 'renren.com',
'key_id': '1',
'captcha_type': 'web_login',
'password': '776f67653bd0b50d6159b7b5173b74249b9e0765da701ff559c986054b9871a7',
'rkey': 'fe41ddb7ec32db83d8bdbcc6945e267a',
'f': 'http%3A%2F%2Fwww.renren.com%2F960481378%2Fprofile',
}
data = urllib.parse.urlencode(data).encode('utf8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=post_url, headers=headers)
response = opener.open(request, data=data)
print(response.read().decode('utf8'))
# with open('renren.html', 'wb') as fp:
# fp.write(response.read())
# 訪問登錄后的頁面
url = 'http://www.renren.com/960481378/profile'
headers1 = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers1)
response = opener.open(request)
with open('renren.html', 'wb') as fp:
fp.write(response.read())
2猿挚、正則表達(dá)式
為什么引入正則表達(dá)式咐旧?
字符串,處理函數(shù)也非常重要绩蜻,比如如果要去一個(gè)文件查找所有的郵箱
test@163.com
889910@qq.com正則表達(dá)式铣墨。可以匹配一類的東西办绝,肯定有好多規(guī)則
世界上最難懂四種東西伊约。女人的心,醫(yī)生的處方孕蝉、道士的符屡律、程序媛的正則
正則表達(dá)式規(guī)則
1.單字符匹配:
. : 除了換行符以外所有的字符
\d : 匹配 0-9 [0-9] [1-5]
\D: 除了\d
\w : 數(shù)字、字母降淮、下劃線 [a-zA-Z0-9_]
\W : 除了\w
\s : 所有的空白字符超埋,tab、空格 佳鳖。霍殴。。
\S : 除了\s
[aeiou] : 匹配中括號(hào)里面任意個(gè)
2.數(shù)量修飾:
{5} : 修飾前面的字符出現(xiàn)5次
{5,8} : 5-8次
a{5,8}
aaaaaaaa 貪婪的
{5,} : 最少是5次
{0,} : 任意多次 *
{1,} : 至少1次 +
{0,1} : 可有可無 ?
python模塊 re
re.match(): >>>> 從頭開始匹配系吩,匹配成功就返回
re.search() >>>> 從任意位置開始匹配来庭,匹配成功返回 只找一個(gè)
返回的是對(duì)象, >>>> obj.group()
re.findall() :>>>>>查找所有符合要求的字符串
返回的是列表穿挨,列表里面都是匹配成功的字符串
3.邊界:
^ : 以xxx開頭
$ : 以xxx結(jié)尾
4.分組:
a(bc){5}
小括號(hào)作用
- (1)視為一個(gè)整體
- (2)子模式
貪婪模式:
.*
.+
.*? 取消貪婪
.+? 取消貪婪
模式修正
re.I : 忽略大小寫
re.M : 視為多行模式
re.S : 視為單行模式
import re
# 創(chuàng)建正則對(duì)象
pattern = re.compile(r'\d{3,5}')
string = '我以前總共談過1234567次戀愛,我總共結(jié)婚7654321次'
# ret = pattern.match(string)
# ret = pattern.search(string)
ret = pattern.findall(string)
print(ret)
pattern = re.compile(r'a(bc){3}')
string = '哈哈呵呵abcbcbcbcbc嘻嘻嘿嘿么么'
ret = pattern.search(string)
print(ret.group())
string = '哈哈<div><span>醉臥沙場(chǎng)君莫笑,古來征戰(zhàn)幾人回</span></div>嘻嘻'
pattern = re.compile(r'<(\w+)><(\w+)>.+</\2></\1>')
ret = pattern.search(string)
print(ret.group())
string = '<div>兩岸猿聲啼不住,輕舟已過萬重山</div></div></div>'
pattern = re.compile(r'<div>.*?</div>')
ret = pattern.search(string)
print(ret.group())
"""
string = '''english
love is a forever problem
love is feel
'''
pattern = re.compile(r'^love', re.M)
ret = pattern.search(string)
print(ret.group())
"""
"""
string = '''<div>細(xì)思極恐
你的對(duì)手在看書
你的敵人在磨刀
你的閨蜜在減肥
隔壁老王在練腰
</div>
'''
pattern = re.compile(r'<div>.*</div>', re.S)
ret = pattern.search(string)
print(ret.group())
"""
def fn(ret):
number = int(ret.group())
number += 1
return str(number)
# 正則替換
string = '男人都喜歡19歲的女孩'
pattern = re.compile(r'\d+')
# ret = pattern.sub('40', string)
ret = pattern.sub(fn, string)
print(ret)
糗事百科圖片--實(shí)戰(zhàn)
import urllib.request
import urllib.parse
import re
import os
import time
def handle_request(url, page):
url += str(page) + '/'
# print(url)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
return request
def parse_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf8')
with open('lala.html', 'w', encoding='utf8') as fp:
fp.write(content)
# 解析內(nèi)容月弛,提取這一頁所有的圖片鏈接
pattern = re.compile(r'<div class="thumb">.*?<a href=".*?" target="_blank">.*?<img src="(.*?)" alt="(.*?)" />.*?</div>', re.S)
ret = pattern.findall(content)
# print(ret)
# exit()
# print(len(ret))
download(ret)
def download(ret):
for image_info in ret:
# 取出圖片的鏈接
image_src = image_info[0]
# 取出圖片的標(biāo)題
image_alt = image_info[1]
# 拼接完整的url
image_src = 'https:' + image_src
dirname = 'tupian'
# 創(chuàng)建文件夾
if not os.path.exists(dirname):
os.mkdir(dirname)
# 得到后綴名
suffix = image_src.split('.')[-1]
# 文件名字
filename = image_alt + '.' + suffix
filepath = os.path.join(dirname, filename)
print('正在下載%s......' % filename)
# 下載圖片
urllib.request.urlretrieve(image_src, filepath)
print('結(jié)束下載%s' % filename)
time.sleep(3)
def main():
start_page = int(input('請(qǐng)輸入要爬取的起始頁碼:'))
end_page = int(input('請(qǐng)輸入要爬取的結(jié)束頁碼:'))
url = 'https://www.qiushibaike.com/pic/page/'
for page in range(start_page, end_page + 1):
print('正在下載第%s頁......' % page)
# 拼接url。構(gòu)建請(qǐng)求對(duì)象
request = handle_request(url, page)
# 發(fā)送請(qǐng)求絮蒿,獲取響應(yīng)尊搬,并且解析內(nèi)容
parse_content(request)
print('結(jié)束下載第%s頁' % page)
time.sleep(3)
if __name__ == '__main__':
main()
勵(lì)志語句--實(shí)戰(zhàn)
import urllib.request
import urllib.parse
import re
import time
def main():
url = 'http://www.yikexun.cn/lizhi/qianming/list_50_{}.html'
start_page = int(input('請(qǐng)輸入起始頁碼:'))
end_page = int(input('請(qǐng)輸入結(jié)束頁碼:'))
# 在這里打開文件
fp = open('lizhi.html', 'w', encoding='utf8')
for page in range(start_page, end_page + 1):
print('正在爬取第%s頁......' % page)
# 拼接url,生成請(qǐng)求對(duì)象
request = handle_request(url, page)
content = urllib.request.urlopen(request).read().decode('utf8')
# 解析內(nèi)容函數(shù)
parse_content(content, fp)
print('結(jié)束爬取第%s頁' % page)
time.sleep(2)
fp.close()
def handle_request(url, page=None):
if page:
url = url.format(page)
# print(url)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
return urllib.request.Request(url=url, headers=headers)
def parse_content(content, fp):
# 寫正則表達(dá)式土涝,提取所有的標(biāo)題和鏈接
pattern = re.compile(r'<h3><a href="(/lizhi/qianming/\d+\.html)">(.*?)</a></h3>')
ret = pattern.findall(content)
# print(ret)
# print(len(ret))
i = 0
for href_title in ret:
# 取出鏈接
+ href_title[0]
# 取出標(biāo)題
title = href_title[1]
print('正在爬取%s......' % title)
# 因?yàn)橹挥械谝粋€(gè)title兩邊有b標(biāo)簽佛寿,所以這里寫了一個(gè)小小的判斷,只在循環(huán)第一次執(zhí)行
if i == 0:
# 將title兩邊的b標(biāo)簽干掉
title = title.strip('<>b/')
i += 1
# print(title)
# 獲取內(nèi)容的函數(shù)
text = get_text(href)
# 將標(biāo)題和內(nèi)容寫入到文件中
string = '<h1>%s</h1>%s' % (title, text)
fp.write(string)
print('結(jié)束爬取%s...' % title)
time.sleep(2)
def get_text(href):
# 構(gòu)建請(qǐng)求對(duì)象但壮,發(fā)送請(qǐng)求冀泻,解析響應(yīng),返回解析后的內(nèi)容
request = handle_request(href)
content = urllib.request.urlopen(request).read().decode('utf8')
pattern = re.compile(r'<div class="neirong">(.*?)</div>', re.S)
ret = pattern.search(content)
# print(ret.group(1))
# exit()
text = ret.group(1)
# 將圖片鏈接去除掉
pattern = re.compile(r'<img .*?>')
text = pattern.sub('', text)
return text
if __name__ == '__main__':
main()
day04-爬蟲4
1蜡饵、bs4語法
是什麼弹渔?
BeautifulSoup,就是一個(gè)第三方的庫溯祸,使用之前需要安裝
pip install bs4
pip進(jìn)行安裝肢专,默認(rèn)是從國外安裝舞肆,所以需要將pip源設(shè)置為國內(nèi)源,國內(nèi)有豆瓣源博杖、阿里源椿胯、網(wǎng)易源等等xxx
配置永久國內(nèi)源:
- 1.windows配置方式:
(1)打開文件資源管理器
--------在地址欄中輸入 %appdata%
(2)手動(dòng)創(chuàng)建一個(gè)文件夾叫做 pip
(3)在pip的文件夾里面新建一個(gè)文件 pip.ini
(4)文件中寫如下內(nèi)容[global] index-url = http://pypi.douban.com/simple [install] trusted-host=pypi.douban.com
- linux配置方式:
(1)cd ~
(2)mkdir .pip
(3)vi ~/.pip/pip.conf
(4)編輯內(nèi)容和windows的內(nèi)容一模一樣
pip install bs4 pip install lxml
bs4是什麼?
- 它的作用是能夠快速方便簡(jiǎn)單的提取網(wǎng)頁中指定的內(nèi)容剃根,給我一個(gè)網(wǎng)頁字符串哩盲,然后使用它的接口將網(wǎng)頁字符串生成一個(gè)對(duì)象,然后通過這個(gè)對(duì)象的方法來提取數(shù)據(jù)
lxml是什麼狈醉?
- lxml是一個(gè)解析器廉油,也是下面的xpath要用到的庫,bs4將網(wǎng)頁字符串生成對(duì)象的時(shí)候需要用到解析器苗傅,就用lxml抒线,或者使用官方自帶的解析器 html.parser
bs4語法學(xué)習(xí)
- 通過本地文件進(jìn)行學(xué)習(xí),通過網(wǎng)絡(luò)進(jìn)行寫代碼
(1)根據(jù)標(biāo)簽名進(jìn)行獲取節(jié)點(diǎn)
只能找到第一個(gè)符合要求的節(jié)點(diǎn)
(2)獲取文本內(nèi)容和屬性 - 屬性
soup.a.attrs 返回一字典金吗,里面是所有屬性和值
soup.a['href'] 獲取href屬性
- 文本
soup.a.string
soup.a.text
soup.a.get_text()
【注】當(dāng)標(biāo)簽里面還有標(biāo)簽的時(shí)候十兢,string獲取的為None趣竣,其他兩個(gè)獲取純文本內(nèi)容
(3)find方法
soup.find('a')
soup.find('a', class_='xxx')
soup.find('a', title='xxx')
soup.find('a', id='xxx')
soup.find('a', id=re.compile(r'xxx'))
【注】find只能找到符合要求的第一個(gè)標(biāo)簽摇庙,他返回的是一個(gè)對(duì)象
(4)find_all
返回一個(gè)列表,列表里面是所有的符合要求的對(duì)象
soup.find_all('a')
soup.find_all('a', class_='wang')
soup.find_all('a', id=re.compile(r'xxx'))
soup.find_all('a', limit=2) 提取出前兩個(gè)符合要求的a
(5)select
選擇遥缕,選擇器 css中
常用的選擇器
標(biāo)簽選擇器卫袒、id選擇器、類選擇器
層級(jí)選擇器**
div h1 a 后面的是前面的子節(jié)點(diǎn)即可
div > h1 > a 后面的必須是前面的直接子節(jié)點(diǎn)
屬性選擇器
input[name='hehe']
select('選擇器的')
【注】返回的是一個(gè)列表单匣,列表里面都是對(duì)象
【注】find find_all select不僅適用于soup對(duì)象夕凝,還適用于其他的子對(duì)象,如果調(diào)用子對(duì)象的select方法户秤,那么就是從這個(gè)子對(duì)象里面去找符合這個(gè)選擇器的標(biāo)簽
from bs4 import BeautifulSoup
# 生成soup對(duì)象
soup = BeautifulSoup(open('soup.html', encoding='utf8'), 'lxml')
print(type(soup))
print(soup.a.attrs)
print(soup.a.attrs['href'])
print(soup.a['href'])
print(soup.a.string)
print(soup.a.text)
print(soup.a.get_text())
print(soup.div.string)
print(soup.div.text)
print(soup.div.get_text())
ret = soup.find('a')
ret = soup.find('a', title='清明')
ret = soup.find('a', class_='dumu')
print(ret)
import re
ret = soup.find('a', id='xiaoge')
ret = soup.find('a', id=re.compile(r'^x'))
print(ret.string)
ret = soup.find_all('a')
print(ret[1].string)
ret = soup.find_all('a', class_='wang')
print(ret)
ret = soup.find_all('a', id=re.compile(r'^x'))
print(ret)
ret = soup.select('a')
ret = soup.select('#muxiong')
print(ret[0]['title'])
ret = soup.select('.wang')
print(ret)
ret = soup.select('div > a')
print(ret)
ret = soup.select('a[title=東坡肉]')
print(ret)
odiv = soup.select('.tang')[0]
ret = odiv.select('a')
print(ret)
滾滾長(zhǎng)江東逝水码秉,浪花淘盡英雄,是非成敗轉(zhuǎn)頭看鸡号,青山依舊在转砖,幾度夕陽紅
白發(fā)漁樵江渚上,觀看秋月春風(fēng)鲸伴,一壺濁酒喜相逢府蔗,古今多少事,都付笑談中
三國演義--實(shí)戰(zhàn)
import urllib.request
import urllib.parse
from bs4 import BeautifulSoup
import time
# 給我一個(gè)url汞窗,返回一個(gè)請(qǐng)求對(duì)象
def handle_request(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
return urllib.request.Request(url=url, headers=headers)
def parse_first_page(url):
request = handle_request(url)
# 發(fā)送請(qǐng)求姓赤,獲取響應(yīng)
content = urllib.request.urlopen(request).read().decode('utf8')
time.sleep(2)
# 使用bs解析內(nèi)容,生成soup對(duì)象
soup = BeautifulSoup(content, 'lxml')
# print(soup)
# 查找所有的章節(jié)鏈接對(duì)象
a_list = soup.select('.book-mulu > ul > li > a')
# print(ret)
# print(len(ret))
# 打開文件
fp = open('三國演義.txt', 'w', encoding='utf8')
# 遍歷所有的a對(duì)象
for oa in a_list:
# 取出這個(gè)a的內(nèi)容
title = oa.string
# 取出a的href屬性
+ oa['href']
print('正在下載%s......' % title)
# 向href發(fā)送請(qǐng)求,直接獲取到解析之后的內(nèi)容
neirong = get_neirong(href)
print('結(jié)束下載%s' % title)
time.sleep(2)
string = '%s\n%s' % (title, neirong)
# 將string寫入到文件中
fp.write(string)
fp.close()
def get_neirong(href):
# 向href發(fā)送請(qǐng)求仲吏,獲取響應(yīng)不铆,解析響應(yīng)蝌焚,返回內(nèi)容
request = handle_request(href)
content = urllib.request.urlopen(request).read().decode('utf8')
# 生成soup對(duì)象,提取章節(jié)內(nèi)容
soup = BeautifulSoup(content, 'lxml')
# 找包含章節(jié)內(nèi)容的div
odiv = soup.find('div', class_='chapter_content')
neirong = odiv.text
return neirong
def main():
url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
# 解析第一個(gè)頁面誓斥,返回所有的章節(jié)列表
chapter_list = parse_first_page(url)
if __name__ == '__main__':
main()
智聯(lián)招聘--實(shí)戰(zhàn)
import urllib.request
import urllib.parse
import time
from bs4 import BeautifulSoup
class ZhiLianSpider(object):
def __init__(self, jl, kw, start_page, end_page):
# 保存到成員屬性中综看,這樣在其他的方法中就可以直接使用
self.jl = jl
self.kw = kw
self.start_page = start_page
self.end_page = end_page
self.items = []
def handle_request(self, page):
url = 'https://sou.zhaopin.com/jobs/searchresult.ashx?'
data = {
'jl': self.jl,
'kw': self.kw,
'p': page,
}
query_string = urllib.parse.urlencode(data)
# 拼接url
url += query_string
# print(url)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
return urllib.request.Request(url=url, headers=headers)
def parse_content(self, content):
# 生成soup對(duì)象
soup = BeautifulSoup(content, 'lxml')
# 首先找到所有的table
table_list = soup.find_all('table', class_='newlist')[1:]
# print(table_list)
# print(len(table_list))
# 遍歷所有的table,依次提取每一個(gè)工作的信息
for table in table_list:
# 職位名稱
zwmc = table.select('.zwmc a')[0].text.strip('\xa0')
# 公司名稱
gsmc = table.select('.gsmc a')[0].text
# 職位月薪
zwyx = table.select('.zwyx')[0].text
# 工作地點(diǎn)
gzdd = table.select('.gzdd')[0].text
# print(gzdd)
# exit()
item = {
'職位名稱': zwmc,
'公司名稱': gsmc,
'職位月薪': zwyx,
'工作地點(diǎn)': gzdd,
}
self.items.append(item)
def run(self):
# 搞個(gè)循環(huán)
for page in range(self.start_page, self.end_page + 1):
print('正在爬取第%s頁......' % page)
# 拼接url的過程岖食,構(gòu)建請(qǐng)求對(duì)象
request = self.handle_request(page)
content = urllib.request.urlopen(request).read().decode('utf8')
# 給我請(qǐng)求對(duì)象红碑,解析并且提取內(nèi)容
self.parse_content(content)
print('結(jié)束爬取第%s頁' % page)
time.sleep(2)
# 將所有的工作保存到文件中
string = str(self.items)
with open('work.txt', 'w', encoding='utf8') as fp:
fp.write(string)
def main():
# 輸入工作地點(diǎn)
jl = input('請(qǐng)輸入工作地點(diǎn):')
# 輸入工作關(guān)鍵字
kw = input('請(qǐng)輸入關(guān)鍵字:')
# 輸入起始頁碼
start_page = int(input('請(qǐng)輸入起始頁碼:'))
# 輸入結(jié)束頁碼
end_page = int(input('請(qǐng)輸入結(jié)束頁碼:'))
zhilian = ZhiLianSpider(jl, kw, start_page, end_page)
zhilian.run()
if __name__ == '__main__':
main()
2、xpath語法
xml : 和json是一樣的泡垃,用在數(shù)據(jù)交互和傳輸中析珊,但是到現(xiàn)在用的基本上都是json格式
為什么使用json格式?因?yàn)閖s原生支持
xpath : 就是用來解析xml數(shù)據(jù)的
因?yàn)檫@個(gè)xml和html很像蔑穴,所以在python里面有一個(gè)第三方庫 lxml忠寻,提供了一些xpath可以解析html的一些函數(shù),你可以直接使用
pip install lxml
xpath簡(jiǎn)單語法:
/ ----------根節(jié)點(diǎn)開始查找
// --------從任意位置開始查找
. ---------從當(dāng)前節(jié)點(diǎn)開始查找
.. -----從上一級(jí)節(jié)點(diǎn)開始查找
@ -----------選取屬性
bookstore/book :查找bookstore這個(gè)節(jié)點(diǎn)下面所有的book存和,直接子節(jié)點(diǎn)
//book : 在整個(gè)文檔中查找所有的book
bookstore//book :查找bookstore下面所有的book
//@lang :-查找所有擁有l(wèi)ang屬性的節(jié)點(diǎn)
bookstore/book[1] :查找第一個(gè)book奕剃,下標(biāo)從1開始
bookstore/book[last()] :-最后一個(gè)book
bookstore/book[last()-1] : 倒數(shù)第二個(gè)
//title[@lang] :所有的有l(wèi)ang屬性的title
//title[@lang='eng'] :所有的lang屬性的值為eng的title節(jié)點(diǎn)
day05-爬蟲5
1、xpath使用
安裝xpath插件
- 啟動(dòng)和關(guān)閉插件: ctrl + shift + x
常用的xpath
(1)屬性定位
- 查找id=kw的input框
//input[@id="kw"]
(2)層級(jí)和索引定位
//div[@id="head"]/div/div[3]/a[2]
(3)模糊匹配
contains
class屬性包含av的所有a
//a[contains(@class,"av")]
內(nèi)容包含產(chǎn)品的所有a
//a[contains(text(),"產(chǎn)品")]
starts_with
starts-with
class以m開頭的所有a
//a[starts-with(@class,"m")]
內(nèi)容以新開頭的所有a
//a[starts-with(text(),"新")]
(4)取文本和屬性
- 找內(nèi)容以新開頭的所有a標(biāo)簽的文本內(nèi)容
//a[starts-with(text(),"新")]/text()
- 找內(nèi)容以新開頭的所有a標(biāo)簽的href屬性
//a[starts-with(text(),"新")]/@href
代碼中操作xpath
步驟:給一個(gè)網(wǎng)頁字符串捐腿,會(huì)將網(wǎng)頁字符串生成對(duì)象纵朋,然后根據(jù)對(duì)象的xpath方法去找指定的節(jié)點(diǎn)即可
from lxml import etree
# 將本地的文件生成tree對(duì)象
tree = etree.parse('xpath.html')
# ret = tree.xpath('//li[@id="fei"]')
# ret = tree.xpath('//div[@class="mingju"]/ul/li[2]/a')
# ret = tree.xpath('//li[contains(text(),"花")]')
# ret = tree.xpath('//a[starts-with(@class,"y")]/text()')
# ret = tree.xpath('//a[starts-with(@class,"y")]/@href')
ret = tree.xpath('//div[@id="xing"]//text()')
string = '-'.join(ret).replace('\n', '').replace('\t', '')
print(string)
本地測(cè)試
【注】獲取標(biāo)簽里面還有標(biāo)簽的內(nèi)容的時(shí)候
obj/text() 只能找到本標(biāo)簽里面的內(nèi)容,返回的都是列表茄袖,列表需要自己處理
obj//text() 標(biāo)簽里面所有的內(nèi)容操软,返回的是列表,列表需要處理
下載圖片例子
sc.chinaz.com
http://sc.chinaz.com/tag_tupian/YaZhouMeiNv.html 第一頁
http://sc.chinaz.com/tag_tupian/yazhoumeinv_2.html 第二頁
from lxml import etree
import time
import urllib.request
import urllib.parse
import os
def handle_request(url, url_er, page):
if page == 1:
url = url
else:
url = url_er.format(page)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
return urllib.request.Request(url=url, headers=headers)
def parse_content(content):
# 生成tree對(duì)象
tree = etree.HTML(content)
# 寫xpath宪祥,來獲取所有的圖片的image_src
image_src_list = tree.xpath('//div[@id="container"]//img/@src2')
image_alt_list = tree.xpath('//div[@id="container"]//img/@alt')
# print(image_src_list)
# print(len(image_src_list))
for image_src in image_src_list:
dirname = 'meinv'
if not os.path.exists(dirname):
os.mkdir(dirname)
filename = image_alt_list[image_src_list.index(image_src)]
suffix = image_src.split('.')[-1]
filename = filename + '.' + suffix
filepath = os.path.join(dirname, filename)
print('正在下載%s聂薪。。蝗羊。席吴。哮翘。匙姜。' % filename)
urllib.request.urlretrieve(image_src, filepath)
print('結(jié)束下載%s' % filename)
time.sleep(2)
def main():
start_page = int(input('請(qǐng)輸入起始頁碼:'))
end_page = int(input('請(qǐng)輸入結(jié)束頁碼:'))
url = 'http://sc.chinaz.com/tag_tupian/YaZhouMeiNv.html'
url_er = 'http://sc.chinaz.com/tag_tupian/yazhoumeinv_{}.html'
for page in range(start_page, end_page + 1):
print('正在下載第%s頁厂汗。。涯呻。凉驻。。复罐。' % page)
request = handle_request(url, url_er, page)
content = urllib.request.urlopen(request).read().decode('utf8')
# 解析內(nèi)容函數(shù)
parse_content(content)
print('結(jié)束下載第%s頁' % page)
time.sleep(2)
if __name__ == '__main__':
main()
懶加載技術(shù)
只顯示可視區(qū)內(nèi)的圖片涝登,不再可視區(qū)內(nèi)的不顯示,等用戶滾動(dòng)滾動(dòng)條效诅,圖片呈現(xiàn)在可視區(qū)的時(shí)候在顯示
如何實(shí)現(xiàn)的胀滚?
<img src='xxx'>
<img src2='xxx'> => 出現(xiàn)在可視區(qū)趟济,js動(dòng)態(tài)修改為 <img src='xxx'>
data-original=xxx
class='lazy'
data-src='xxx'
json處理
- 獲取豆瓣電影的json數(shù)據(jù)寫入txt
import json
import urllib.request
import urllib.parse
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=20&limit=20'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
content = urllib.request.urlopen(request).read().decode('utf8')
# print(content)
# 將json格式數(shù)據(jù)轉(zhuǎn)化為python對(duì)象
obj = json.loads(content)
# print(type(obj))
# 現(xiàn)在的obj是一個(gè)列表,列表里面都是字典
lt = []
# 遍歷列表咽笼,依次提取每一個(gè)字典里面的電影的名字和評(píng)分
for movie in obj:
title = movie['title']
score = movie['score']
# movie['xixi']['hehe']['haha'][0]['lala']
image_url = movie['cover_url']
item = {
'電影名字': title,
'電影評(píng)分': score,
'電影海報(bào)': image_url
}
lt.append(item)
string = json.dumps(lt, ensure_ascii=False)
with open('movie1.txt', 'w', encoding='utf8') as fp:
fp.write(string)
2顷编、jsonpath
jsonpath是用來解析json數(shù)據(jù)的
格式: {} [] "" , :
python如何解析json格式
(1)自帶數(shù)據(jù)類型進(jìn)行解析
import json
json.dumps() : 將python對(duì)象轉(zhuǎn)化為json格式字符串
ensure_ascii=False 寫入文件中文顯示
json.loads() : 將json格式字符串轉(zhuǎn)化為python對(duì)象
(2)jsonpath解析(了解)
pip install jsonpath
http://blog.csdn.net/luxideyao/article/details/77802389
/ $ 根元素
. @ 當(dāng)前元素
/ . 層級(jí)分隔符
// .. 任意位置查找
- jsonpath使用規(guī)則
import json
import jsonpath
fp = open('book.json', 'r', encoding='utf8')
string = fp.read()
fp.close()
# 將json格式字符串轉(zhuǎn)化為python對(duì)象
obj = json.loads(string)
# 使用jsonpath
# 查找所有book的author節(jié)點(diǎn)內(nèi)容
# ret = jsonpath.jsonpath(obj, '$.store.book[*].author')
# 從根下面開始找所有的author
ret = jsonpath.jsonpath(obj, '$..author')
# 查找store下面的所有節(jié)點(diǎn)
ret = jsonpath.jsonpath(obj, '$.store.*')
# 查找store下面的所有price節(jié)點(diǎn)
ret = jsonpath.jsonpath(obj, '$.store..price')
# 查找第三本book
ret = jsonpath.jsonpath(obj, '$..book[2]')
# 查找最后一本書籍
ret = jsonpath.jsonpath(obj, '$..book[(@.length-1)]')
print(ret)
淘寶評(píng)論---實(shí)戰(zhàn)
用戶頭像,用戶昵稱,評(píng)論內(nèi)容,評(píng)論圖片,評(píng)論時(shí)間,手機(jī)信息
https://rate.taobao.com/feedRateList.htm?auctionNumId=559141739630&userNumId=100340983¤tPageNum=3&pageSize=20
import json
import jsonpath
import urllib.request
import urllib.parse
import time
# 用來存放所有的評(píng)論信息
items = []
def handle_request(page, url):
url = url.format(page)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
return urllib.request.Request(url=url, headers=headers)
def parse_content(content):
# 如何解析content
# 處理content,將其轉(zhuǎn)化為合法的json格式字符串
content = content.strip('() \n\t\r')
# print(content)
obj = json.loads(content)
# print(type(obj))
# 提取出來所有的評(píng)論
comments_list = obj['comments']
# 遍歷列表剑刑,依次提取每一條評(píng)論的你要的信息
for comment in comments_list:
# 用戶頭像
# avatar = comment['user']['avatar']
avatar = jsonpath.jsonpath(comment, '$..avatar')[0]
# 用戶昵稱
nick = comment['user']['nick']
# 評(píng)論內(nèi)容
neirong = comment['content']
# 圖片
photos_list = comment['photos']
photos = []
for photo in photos_list:
# 獲取小圖
little_image = photo['thumbnail']
# 獲取大圖
big_image = photo['url']
photos.append((little_image, big_image))
# 時(shí)間
ping_time = comment['date']
# 手機(jī)信息
info = jsonpath.jsonpath(comment, '$..sku')[0]
item = {
'用戶頭像': avatar,
'用戶昵稱': nick,
'評(píng)論內(nèi)容': neirong,
'曬圖': photos,
'評(píng)論時(shí)間': ping_time,
'手機(jī)信息': info,
}
items.append(item)
def main():
url = 'https://rate.taobao.com/feedRateList.htm?auctionNumId=559141739630&userNumId=100340983¤tPageNum={}&pageSize=20'
start_page = int(input('請(qǐng)輸入起始頁碼:'))
end_page = int(input('請(qǐng)輸入結(jié)束頁碼:'))
for page in range(start_page, end_page + 1):
# for page in range(1, 2):
print('正在爬取第%s頁......' % page)
request = handle_request(page, url)
content = urllib.request.urlopen(request).read().decode('utf8')
parse_content(content)
print('結(jié)束爬取第%s頁......' % page)
time.sleep(2)
# 爬取完畢, 寫入到文件中
string = json.dumps(items, ensure_ascii=False)
with open('taobao.json', 'w', encoding='utf8') as fp:
fp.write(string)
if __name__ == '__main__':
main()
3媳纬、selenium+phantomjs
http://chromedriver.storage.googleapis.com/index.html
http://blog.csdn.net/huilan_same/article/details/51896672
day06-爬蟲6
1、selenium+phantomjs
selenium是什麼施掏?
是一個(gè)瀏覽器自動(dòng)化測(cè)試工具钮惠,自動(dòng)化就是通過代碼操作瀏覽器,讓瀏覽器自動(dòng)的做一些操作七芭,是python的第三方庫素挽,需要安裝才能使用
pip install selenium
谷歌驅(qū)動(dòng)下載地址
http://chromedriver.storage.googleapis.com/index.html
驅(qū)動(dòng)和瀏覽器版本關(guān)系映射表
http://blog.csdn.net/huilan_same/article/details/51896672
selenium 操作谷歌瀏覽器
需要有一個(gè)谷歌瀏覽器的驅(qū)動(dòng),然后操作這個(gè)驅(qū)動(dòng)
from selenium import webdriver
import time
# 根據(jù)webdriver里面的類去創(chuàng)建一個(gè)谷歌瀏覽器對(duì)象
path = r'C:\Users\ZBLi\Desktop\1805\day06\ziliao\chromedriver.exe'
browser = webdriver.Chrome(path)
# 再往下狸驳,操作瀏覽器就是操作對(duì)象
# 打開百度
url = 'http://www.baidu.com/'
browser.get(url)
time.sleep(2)
# 查找百度輸入框
my_input = browser.find_element_by_id('kw')
# 寫內(nèi)容
my_input.send_keys('清純美女')
time.sleep(2)
# 查找按鈕框
button = browser.find_element_by_id('su')
button.click()
time.sleep(3)
# 查找陽光美女鏈接
href = browser.find_elements_by_xpath('//div[@class="op-img-covers-divide-high"][2]/a[2]')[0]
href.click()
time.sleep(3)
# 推出瀏覽器
browser.quit()
find_element_by_id 根據(jù)id找固定的節(jié)點(diǎn)
find_elements_by_name 根據(jù)name找節(jié)點(diǎn)
find_elements_by_xpath 根據(jù)xpath查找
find_elements_by_tag_name 根據(jù)標(biāo)簽名查找
find_elements_by_class_name 根據(jù)類名查找
find_elements_by_css_selector 根據(jù)選擇器查找
find_elements_by_link_text 根據(jù)鏈接內(nèi)容查找
作用在哪预明?
讓selenium操作的是phantomjs
phantomjs是什麼?
就是一款瀏覽器耙箍,無界面的瀏覽器撰糠,具有瀏覽器的功能,html\css\js這些文件瀏覽器可以直接執(zhí)行究西。
我們關(guān)注的就是phantomjs可以執(zhí)行js文件的功能窗慎,在爬取網(wǎng)站的時(shí)候,經(jīng)常碰見動(dòng)態(tài)加載數(shù)據(jù)的過程卤材。js DOM,解決方法兩種
(1)抓接口峦失,拿出來接口發(fā)送請(qǐng)求扇丛,解析即可
(2)讓瀏覽器直接執(zhí)行js,然后我要執(zhí)行js之后的網(wǎng)頁代碼尉辑,selenium+phantomjs帆精,終極解決方案,大招隧魄,缺點(diǎn):發(fā)請(qǐng)求之后要有停頓
操作phantomjs
from selenium import webdriver
import time
path = r'C:\Users\ZBLi\Desktop\1805\day06\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe'
browser = webdriver.PhantomJS(path)
browser.get('http://www.baidu.com/')
time.sleep(3)
# 拍照片卓练,記錄走到哪了
browser.save_screenshot(r'tupian\baidu1.png')
browser.find_element_by_id('kw').send_keys('美女')
time.sleep(2)
browser.find_element_by_id('su').click()
time.sleep(3)
browser.save_screenshot(r'tupian\baidu2.png')
browser.quit()
代碼中模擬滾動(dòng)條滾動(dòng)到底部
js = 'document.body.scrollTop=10000'
browser.execute_script(js)
from selenium import webdriver
import time
path = r'C:\Users\ZBLi\Desktop\1805\day06\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe'
browser = webdriver.PhantomJS(path)
url = 'https://movie.douban.com/typerank?type_name=%E5%8A%A8%E4%BD%9C&type=5&interval_id=100:90&action='
browser.get(url)
time.sleep(3)
browser.save_screenshot(r'tupian\douban1.png')
# 執(zhí)行一句js代碼即可
# for x in range(1, 6):
# js = 'document.body.scrollTop=10000'
# browser.execute_script(js)
# time.sleep(3)
# browser.save_screenshot(r'tupian\douban2.png')
js = 'document.body.scrollTop=10000'
browser.execute_script(js)
time.sleep(3)
# 獲取執(zhí)行js之后的網(wǎng)頁代碼
with open(r'tupian\douban.html', 'w', encoding='utf8') as fp:
fp.write(browser.page_source)
# 往下就可以通過bs或者xpath來解析網(wǎng)頁內(nèi)容了
# 模擬點(diǎn)擊加載更多,就是通過browser找到那個(gè)按鈕购啄,讓按鈕執(zhí)行click方法即可
browser.quit()
獲取頁面的執(zhí)行js之后的代碼
browser.page_source
2襟企、Headless Chrome
是什麼?
無頭的谷歌瀏覽器-無界面的谷歌瀏覽器狮含,phantomjs現(xiàn)在已經(jīng)沒人維護(hù)了顽悼,
要求:windows(60+以上)曼振、linux(59+以上)
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
from selenium import webdriver
import time
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
path = r'C:\Users\ZBLi\Desktop\1805\day06\ziliao\chromedriver.exe'
browser = webdriver.Chrome(executable_path=path, chrome_options=chrome_options)
browser.get('http://www.baidu.com/')
time.sleep(2)
browser.save_screenshot(r'tupian\baidu3.png')
browser.quit()
- 當(dāng)然:不僅谷歌有無界面模式,火狐也有蔚龙,ie也有冰评,phantomjs
3、requests
是什麼木羹?
- 是一個(gè)第三方庫甲雅,這個(gè)庫和urllib是一樣的,就是模擬瀏覽器發(fā)送http請(qǐng)求的坑填,requests是對(duì)urllib的一層封裝务荆,所以提供的接口更加的人性化
詳請(qǐng)地址
http://docs.python-requests.org/zh_CN/latest/index.html
安裝方式
pip install requests
get\帶參數(shù)的get
data是一個(gè)參數(shù)字典
r = requests.get(url=url, params=data)
響應(yīng)對(duì)象r
r.text 字符串格式內(nèi)容
r.content 字節(jié)格式內(nèi)容
r.headers 響應(yīng)頭部
r.url 請(qǐng)求url
r.status_code 狀態(tài)碼
import requests
'''
url = 'http://www.baidu.com/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
r = requests.get(url=url, headers=headers)
'''
# r是響應(yīng)對(duì)象
# 網(wǎng)頁的字符串內(nèi)容
# print(r.text)
# 字節(jié)內(nèi)容
# print(r.content)
# 獲取網(wǎng)頁的url
# print(r.url)
# 獲取響應(yīng)頭部
# print(r.headers)
# 獲取狀態(tài)碼
# print(r.status_code)
url = 'https://www.baidu.com/s?'
data = {
'ie': 'utf8',
'wd': '周杰倫'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
r = requests.get(url=url, params=data, headers=headers)
with open(r'tupian\zhou.html', 'wb') as fp:
fp.write(r.content)
post
必應(yīng)翻譯
data是參數(shù)字典
r = requests.post(url=url, data=data)
import requests
post_url = 'https://cn.bing.com/ttranslationlookup?&IG=5C360E60322D4FA4865EEBCF710B93B6&IID=translator.5036.2'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
fromdata = {
'from': 'zh-CHS',
'to': 'en',
'text': '皇上',
}
r = requests.post(url=post_url, data=fromdata, headers=headers)
print(r.text)
會(huì)話
登錄,人人網(wǎng)---獲取保存cooike
s = requests.Session()
s.post()
s.get()
import requests
# 使用會(huì)話技術(shù)穷遂,首先創(chuàng)建一個(gè)會(huì)話
# 往下所有操作函匕,使用s進(jìn)行發(fā)送 s.post s.get
s = requests.Session()
post_url = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2018621432232'
data = {
'email':'17701256561',
'icode':'',
'origURL':'http://www.renren.com/home',
'domain':'renren.com',
'key_id':'1',
'captcha_type':'web_login',
'password':'bd20fe8cf1541a10558676a6eeccb4a1a786cfc09823ddd69d5bbaafc7060292',
'rkey':'227f4ceb2f44827f9de8296ca1ef1c3f',
'f':'https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DaovDobnt13PO-vgvw1r-eSnSe_QNvNGtexiQFzyME-a%26wd%3D%26eqid%3Db5d58b1e000297f4000000025b4d88e3',
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
r = s.post(url=post_url, headers=headers, data=data)
# print(r.text)
url = 'http://www.renren.com/960481378/profile'
r = s.get(url, headers=headers)
with open('renren.html', 'wb') as fp:
fp.write(r.content)
公交爬取
import requests
from lxml import etree
import re
import json
import time
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
def parse_first_page(url):
r = requests.get(url=url, headers=headers)
# 生成一個(gè)tree對(duì)象
tree = etree.HTML(r.text)
# 通過tree對(duì)象查找所有的數(shù)字、字母鏈接
number_href_list = tree.xpath('//div[@class="bus_kt_r1"]/a/@href')
char_href_list = tree.xpath('//div[@class="bus_kt_r2"]/a/@href')
return number_href_list + char_href_list
def parse_second_page(url, all_href, fp):
# 為了拼接完整的url蚪黑,先將右邊的 / 干掉
url = url.rstrip('/')
for href in all_href:
href = url + href
r = requests.get(href, headers=headers)
tree = etree.HTML(r.text)
# 解析盅惜,獲取所有的公交href信息
bus_href_list = tree.xpath('//div[@id="con_site_1"]/a/@href')
bus_name_list = tree.xpath('//div[@id="con_site_1"]/a/text()')
# print(bus_href_list)
# exit()
# 向列表中的url依次發(fā)送請(qǐng)求,解析內(nèi)容
parse_third_page(url, bus_href_list, bus_name_list, fp)
def parse_third_page(url, bus_href_list, bus_name_list, fp):
for bus_href in bus_href_list:
title = bus_name_list[bus_href_list.index(bus_href)]
print('正在爬取%s......' % title)
# 拼接完整的url
bus_href = url + bus_href
# 向每一路公交的詳情頁發(fā)送請(qǐng)求
r = requests.get(url=bus_href, headers=headers)
# 在下面的函數(shù)中忌穿,解析每一路公交的詳細(xì)信息
parse_content(r.text, fp)
print('結(jié)束爬取%s' % title)
time.sleep(1)
def parse_content(content, fp):
tree = etree.HTML(content)
# 獲取線路名稱
name = tree.xpath('//div[@class="bus_i_t1"]/h1/text()')[0]
# 獲取運(yùn)行時(shí)間
runtime = tree.xpath('//div[@class="bus_i_content"]/p[1]/text()')[0]
# 獲取票價(jià)信息
price = tree.xpath('//div[@class="bus_i_content"]/p[2]/text()')[0]
# 公交公司
try:
company = tree.xpath('//div[@class="bus_i_content"]/p[3]/a/text()')[0]
except Exception as e:
company = ''
# 更新時(shí)間
gxsj = tree.xpath('//div[@class="bus_i_content"]/p[last()]/text()')[0]
# 獲取公交路線長(zhǎng)度
try:
length = tree.xpath('//div[@class="bus_label "]/p/text()')[0]
pattern = re.compile(r'\d+\.\d+')
ret = pattern.search(length)
length = ret.group()
except Exception as e:
length = ''
total_list = tree.xpath('//span[@class="bus_line_no"]/text()')
# 獲取上行總站數(shù), 使用正則將總站數(shù)拿走
pattern = re.compile(r'\d+')
up_total = total_list[0]
up_total = pattern.search(up_total).group()
# 獲取下行總站數(shù)
try:
down_total = total_list[1]
down_total = pattern.search(down_total).group()
except Exception as e:
down_total = ''
# 獲取上行的公交站牌信息
up_site_name = tree.xpath('//div[@class="bus_line_site "][1]//a/text()')
# 獲取下行的公交站牌信息
try:
down_site_name = tree.xpath('//div[@class="bus_line_site "][2]//a/text()')
except Exception as e:
down_site_name = []
# 將公交的詳細(xì)信息保存到字典中
item = {
'線路名稱': name,
'運(yùn)行時(shí)間': runtime,
'票價(jià)信息': price,
'公交公司': company,
'更新時(shí)間': gxsj,
'線路長(zhǎng)度': length,
'上行站數(shù)': up_total,
'上行站牌': up_site_name,
'下行站數(shù)': down_total,
'下行站牌': down_site_name,
}
string = json.dumps(item, ensure_ascii=False)
fp.write(string + '\n')
def main():
# 打開文件
fp = open('北京公交路線.txt', 'w', encoding='utf8')
url = 'http://beijing.8684.cn/'
# 獲取所有的數(shù)字抒寂、字母鏈接
all_href = parse_first_page(url)
# 遍歷列表,依次發(fā)送請(qǐng)求掠剑,解析二級(jí)頁面
parse_second_page(url, all_href, fp)
fp.close()
if __name__ == '__main__':
main()
4屈芜、登錄---驗(yàn)證碼
驗(yàn)證碼:
(1)將驗(yàn)證碼下載到本地,讓用戶手動(dòng)輸入
(2)使用軟件識(shí)別朴译,效率不高
(3)使用打碼平臺(tái)井佑,識(shí)別率高
import requests
# 搞一個(gè)會(huì)話
s = requests.Session()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
# 先將驗(yàn)證碼下載到本地
get_url = 'https://so.gushiwen.org/user/login.aspx?from=http://so.gushiwen.org/user/collect.aspx'
r = s.get(get_url, headers=headers)
# 需要向圖片src發(fā)送請(qǐng)求,將驗(yàn)證碼下載到本地
image_src = 'https://so.gushiwen.org/RandCode.ashx'
r = s.get(image_src, headers=headers)
with open('code.png', 'wb') as fp:
fp.write(r.content)
code = input('請(qǐng)輸入驗(yàn)證碼:')
post_url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
data = {
'__VIEWSTATE': 'BvBAwAIKh29BShbC/yKMDsjiElxi+d4wdH3pR2dacgsifqK0rmUzL4Mc9YzHGDc6P6rqB4wMZ39uRj2MpaaSjQtarGnIo6qf1djLGa75XLo/S4b65Uhv2TETKt0=',
'__VIEWSTATEGENERATOR':'C93BE1AE',
'from': 'http://so.gushiwen.org/user/collect.aspx',
'email': '1090509990@qq.com',
'pwd': '123456',
'code': code,
'denglu': '登錄',
}
r = s.post(post_url, headers=headers, data=data)
print(r.text)
多進(jìn)程
多任務(wù):生活中來看眠寿,就是多個(gè)任務(wù)同時(shí)進(jìn)行躬翁,喝酒聊天,開車盯拱,手腳并用盒发,唱歌跳舞
電腦中:錄屏、sublime狡逢、vnc服務(wù)端宁舰、瀏覽器打開等
代碼中:實(shí)現(xiàn)多任務(wù),多進(jìn)程奢浑、多線程
進(jìn)程:電腦中蛮艰,每一個(gè)軟件啟動(dòng)起來都是一個(gè)進(jìn)程,
代碼中:沒有運(yùn)行的時(shí)候稱之為程序殷费,運(yùn)行起來之后就是一個(gè)進(jìn)程
多進(jìn)程:進(jìn)程只有一個(gè)印荔,稱之為主進(jìn)程低葫,子進(jìn)程,要實(shí)現(xiàn)兩個(gè)函數(shù)同時(shí)執(zhí)行仍律,就要通過主進(jìn)程來創(chuàng)建子進(jìn)程
操作系統(tǒng)實(shí)現(xiàn)嘿悬,只是在進(jìn)程之間來回切換,切換的非乘快善涨,看著像同時(shí)執(zhí)行一樣
如何實(shí)現(xiàn)?
面向過程:(process)
p = Process(target=xxx, name=xxx, args=(xxx,))
target: 進(jìn)程啟動(dòng)之后要執(zhí)行的函數(shù)
name: 給進(jìn)程起個(gè)名字
args: 給子進(jìn)程傳遞的參數(shù)草则,是一個(gè)元組
p.start() 啟動(dòng)進(jìn)程
p.join() 讓主進(jìn)程等待子進(jìn)程結(jié)束
os.getpid() 獲取當(dāng)前進(jìn)程id號(hào)
os.getppid() 獲取父進(jìn)程的id號(hào)
from multiprocessing import Process
import time
import os
# 想讓子進(jìn)程1執(zhí)行sing函數(shù)
def sing(a):
print('接受的參數(shù)為%s' % a)
# 進(jìn)程id號(hào)
print('進(jìn)程-%s-開始運(yùn)行' % os.getpid())
print('父進(jìn)程為%s' % os.getppid())
for x in range(1, 5):
print('我在唱小情歌')
time.sleep(1)
# 想讓子進(jìn)程2執(zhí)行dance函數(shù)
def dance(a):
print('進(jìn)程-%s-開始運(yùn)行' % os.getpid())
print('父進(jìn)程為%s' % os.getppid())
for x in range(1, 5):
print('我在跳鋼管舞')
time.sleep(1)
def main():
# 主進(jìn)程
print('主進(jìn)程id號(hào)為%s' % os.getpid())
a = '青花瓷'
# 創(chuàng)建進(jìn)程
p_sing = Process(target=sing, name='唱歌', args=(a,))
p_dance = Process(target=dance, name='跳舞', args=(a,))
# 啟動(dòng)進(jìn)程
p_sing.start()
p_dance.start()
# 獲取進(jìn)程名字
print(p_sing.name)
print(p_dance.name)
# 因?yàn)橹鬟M(jìn)程中有子進(jìn)程的信息钢拧,所以主進(jìn)程必須等子進(jìn)程結(jié)束之后再結(jié)束
p_sing.join()
p_dance.join()
print('主進(jìn)程結(jié)束')
if __name__ == '__main__':
main()
面向?qū)ο螅?/h4>
from multiprocessing import Process
import time
class SingProcess(Process):
def __init__(self, a):
# 如果要重寫構(gòu)造方法,一定得手動(dòng)調(diào)用父類的構(gòu)造方法
super().__init__()
self.a = a
def run(self):
print('傳遞的參數(shù)為%s' % self.a)
for x in range(1, 5):
print('我在唱小情歌')
time.sleep(1)
class DanceProcess(Process):
def run(self):
for x in range(1, 5):
print('我在跳鋼管舞')
time.sleep(1)
def main():
a = '現(xiàn)在很多老歌手為什么不唱歌了'
p_sing = SingProcess(a)
# 啟動(dòng)進(jìn)程炕横,進(jìn)程啟動(dòng)之后默認(rèn)執(zhí)行類里面的run方法
p_sing.start()
# p_dance = DanceProcess()
# p_dance.start()
p_sing.join()
# p_dance.join()
print('主進(jìn)程結(jié)束')
if __name__ == '__main__':
main()
from multiprocessing import Process
import time
class SingProcess(Process):
def __init__(self, a):
# 如果要重寫構(gòu)造方法,一定得手動(dòng)調(diào)用父類的構(gòu)造方法
super().__init__()
self.a = a
def run(self):
print('傳遞的參數(shù)為%s' % self.a)
for x in range(1, 5):
print('我在唱小情歌')
time.sleep(1)
class DanceProcess(Process):
def run(self):
for x in range(1, 5):
print('我在跳鋼管舞')
time.sleep(1)
def main():
a = '現(xiàn)在很多老歌手為什么不唱歌了'
p_sing = SingProcess(a)
# 啟動(dòng)進(jìn)程炕横,進(jìn)程啟動(dòng)之后默認(rèn)執(zhí)行類里面的run方法
p_sing.start()
# p_dance = DanceProcess()
# p_dance.start()
p_sing.join()
# p_dance.join()
print('主進(jìn)程結(jié)束')
if __name__ == '__main__':
main()
多進(jìn)程拷貝源内,拷貝文件夾,假如文件夾里面只有文件份殿。假如有100個(gè)文件膜钓,那么拷貝的時(shí)候先拷貝第一個(gè),然后第二個(gè)卿嘲,然后第三個(gè)====
拷貝一個(gè)文件就是一個(gè)任務(wù)颂斜,那一共100文件,那難道要開辟100個(gè)進(jìn)程嗎拾枣?
進(jìn)程并不是越多越好沃疮,切換占用的時(shí)間越大
練習(xí):多進(jìn)程拷貝
拷貝之前記錄時(shí)間戳,拷貝之后記錄時(shí)間戳梅肤,計(jì)算拷貝的時(shí)間
多進(jìn)程拷貝也是一樣司蔬,哪個(gè)時(shí)間短
引入進(jìn)程池,規(guī)定能創(chuàng)建幾個(gè)進(jìn)程凭语,來了任務(wù)葱她,5個(gè)進(jìn)程
進(jìn)程之間是否共享全局變量
全局變量
進(jìn)程之間是否共享全局變量,不共享
每一個(gè)進(jìn)程都是單獨(dú)的代碼
from multiprocessing import Process
import os
import time
count = 100
# 該進(jìn)程用來修改全局變量的值
def change():
global count
count += 100
print('進(jìn)程%s修改后的值為%s' % (os.getpid(), count))
# 該進(jìn)程用來讀取全局變量的值
def read():
print('進(jìn)程%s讀取的值為%s' % (os.getpid(), count))
def test(c):
a = 100
if c == 'hello':
a += 100
time.sleep(2)
print('進(jìn)程%s修改a的值為%s' % (os.getpid(), a))
else:
time.sleep(5)
print('進(jìn)程%s讀取a的值為%s' % (os.getpid(), a))
def main():
'''
p1 = Process(target=change)
p1.start()
time.sleep(2)
p2 = Process(target=read)
p2.start()
'''
a = 'hello'
b = 'world'
p1 = Process(target=test, args=(a, ))
p2 = Process(target=test, args=(b, ))
p1.start()
p2.start()
p1.join()
p2.join()
if __name__ == '__main__':
main()
進(jìn)程池
from multiprocessing import Process
from multiprocessing import Pool
import os
import time
def test(name):
print('任務(wù)%s正在運(yùn)行,進(jìn)程id號(hào)為%s' % (name, os.getpid()))
time.sleep(2)
def main():
# 創(chuàng)建一個(gè)進(jìn)程池對(duì)象
po = Pool(3)
# 給進(jìn)程池添加任務(wù)
lt = ['關(guān)羽', '趙云', '張飛', '馬超', '黃忠', '呂布', '孫策', '大喬']
for name in lt:
po.apply_async(test, args=(name, ))
# 進(jìn)程池使用完畢之后似扔,關(guān)閉
po.close()
# 讓主進(jìn)程等待結(jié)束
po.join()
print('主進(jìn)程、進(jìn)程池全部結(jié)束')
if __name__ == '__main__':
main()
多線程
線程:比如qq搓谆。比如暴風(fēng)影音炒辉,比如word
可以同時(shí)語音、同時(shí)視頻泉手、同時(shí)聊天黔寇,多線程
暴風(fēng)影音,視頻播放斩萌、音頻播放缝裤,多線程
word屏轰,打字,拼寫檢查憋飞,等霎苗,多線程
多任務(wù)的實(shí)現(xiàn):多進(jìn)程、多線程
主進(jìn)程-子進(jìn)程1-子進(jìn)程2
特點(diǎn):進(jìn)程之間沒有關(guān)系榛做,如果一個(gè)進(jìn)程掛了唁盏,不影響其它子進(jìn)程
進(jìn)程-主線程-子線程1-子線程2
特點(diǎn):線程之間有關(guān)系,如果一個(gè)線程掛了检眯,整個(gè)進(jìn)程就掛了
實(shí)現(xiàn)方式:(thread)
面向過程
t = Thread(target=xxx, name=xxx, args=(xxx,))
target: 線程啟動(dòng)之后要執(zhí)行的函數(shù)
name: 線程的名字
args: 給線程傳遞的參數(shù)
t.start(): 啟動(dòng)線程
t.join(): 讓主線程等待子線程結(jié)束
threading.current_thread().name : 獲取線程名字
import threading
import time
def sing(song):
print('傳遞過來的參數(shù)為%s' % song)
print('獲取線程的名字為%s' % threading.current_thread().name)
for x in range(1, 5):
print('我在唱老情歌')
time.sleep(1)
def dance():
for x in range(1, 5):
print('我在跳廣場(chǎng)舞')
time.sleep(1)
def main():
a = '廣島之戀'
# 這是一個(gè)進(jìn)程厘擂,進(jìn)程里面有一個(gè)主線程,然后主線程創(chuàng)建子線程1(唱歌)锰瘸,子線程2(跳舞)
t_sing = threading.Thread(target=sing, name='唱歌', args=(a, ))
t_dance = threading.Thread(target=dance, name='跳舞')
# 啟動(dòng)線程
t_sing.start()
t_dance.start()
t_sing.join()
t_dance.join()
print('主線程刽严、子線程同時(shí)結(jié)束')
if __name__ == '__main__':
main()
面向?qū)ο?/h3>
import threading
import time
# 滕王閣序 王勃
# 命硬
# 沁園春-雪
# 出師表
class MyThread(threading.Thread):
def __init__(self, a):
super().__init__()
self.a = a
def run(self):
print('傳遞過來的參數(shù)為%s' % self.a)
for x in range(1, 5):
print('鳳凰臺(tái)上鳳凰游,鳳去臺(tái)空江自流')
time.sleep(1)
def main():
a = '落霞與孤鶩齊飛,秋水共長(zhǎng)天一色'
t = MyThread(a)
t.start()
t.join()
print('主線程避凝、子線程全部結(jié)束')
if __name__ == '__main__':
main()
是否共享
import threading
import time
# 滕王閣序 王勃
# 命硬
# 沁園春-雪
# 出師表
class MyThread(threading.Thread):
def __init__(self, a):
super().__init__()
self.a = a
def run(self):
print('傳遞過來的參數(shù)為%s' % self.a)
for x in range(1, 5):
print('鳳凰臺(tái)上鳳凰游,鳳去臺(tái)空江自流')
time.sleep(1)
def main():
a = '落霞與孤鶩齊飛,秋水共長(zhǎng)天一色'
t = MyThread(a)
t.start()
t.join()
print('主線程避凝、子線程全部結(jié)束')
if __name__ == '__main__':
main()
全局變量
共享全局變量
局部變量
不共享局部變量
線程安全問題
線程之間可以共享全局變量
import threading
import os
import time
count = 100
# 該線程用來修改全局變量的值
def change():
global count
count += 100
print('線程%s修改后的值為%s' % (threading.current_thread().name, count))
# 該線程用來讀取全局變量的值
def read():
print('線程%s讀取的值為%s' % (threading.current_thread().name, count))
def test():
a = 100
name = threading.current_thread().name
if name == 'lala':
a += 100
time.sleep(2)
print('線程%s修改a的值為%s' % (name, a))
else:
time.sleep(5)
print('線程讀取a的值為%s' % a)
def main():
'''
t1 = threading.Thread(target=change, name='修改thread')
t1.start()
time.sleep(2)
t2 = threading.Thread(target=read, name='讀取thread')
t2.start()
'''
t1 = threading.Thread(target=test, name='lala')
t2 = threading.Thread(target=test)
t1.start()
t2.start()
t1.join()
t2.join()
if __name__ == '__main__':
main()
加鎖
加鎖
lock.acquire()
釋放鎖
lock.release()
import threading
import time
count = 100
# 創(chuàng)建一把鎖
lock = threading.Lock()
def test(number):
start = time.time()
# 在這里面修改count的值
global count
for x in range(1, 10000000):
# 加鎖
lock.acquire()
count += number
count -= number
# 釋放鎖
lock.release()
end = time.time()
# 上廁所舞萄,大號(hào),如何解決恕曲,加鎖
# 用之前鹏氧,加鎖,用完之后佩谣,釋放鎖
# 犧牲了效率了
print('循環(huán)計(jì)算的時(shí)間為%s' % (start - end))
def main():
t1 = threading.Thread(target=test, args=(3, ))
t2 = threading.Thread(target=test, args=(5, ))
t2.start()
t1.start()
t1.join()
t2.join()
print('主線程中打印的count的值為%s' % count)
if __name__ == '__main__':
main()
隊(duì)列
隊(duì)列:買火車票把还,電動(dòng)三輪,特點(diǎn):先進(jìn)先出
用在哪茸俭?
線程之間使用隊(duì)列進(jìn)行交互吊履,讓線程解耦合,生產(chǎn)者-消費(fèi)者模型
線程1-生產(chǎn)數(shù)據(jù)
交互渠道:隊(duì)列
線程2-消費(fèi)數(shù)據(jù)
while 1:
生產(chǎn)數(shù)據(jù)
消費(fèi)數(shù)據(jù)
隊(duì)列使用:
from queue import Queue
q = Queue(5)
q.put() 添加元素
q.put(False) 如果隊(duì)列已滿调鬓,添加元素立即拋出異常
q.put(True, 5) 如果隊(duì)列已滿艇炎,添加元素5s之后拋出異常
q.get() 獲取元素
q.get(False) 如果隊(duì)列為空,獲取元素立即拋出異常
q.get(True, 5) 如果隊(duì)列為空腾窝,獲取元素5s之后拋出異常
q.empty() 隊(duì)列是否為空
q.full() 隊(duì)列是否已滿
q.qsize() 隊(duì)列長(zhǎng)度
from queue import Queue
# 創(chuàng)建一個(gè)隊(duì)列
# 如果寫缀踪,代表隊(duì)列的長(zhǎng)度,如果不寫虹脯,隊(duì)列長(zhǎng)度無限
q = Queue(5)
print(q.empty())
print(q.full())
print(q.qsize())
# 向隊(duì)列中添加數(shù)據(jù)
q.put('吳彥祖')
q.put('岳云鵬')
q.put('王寶強(qiáng)')
q.put('黃渤')
q.put('劉德華')
print(q.empty())
print(q.full())
print(q.qsize())
# q.put('古天樂', True, 5)
# 從隊(duì)列中獲取數(shù)據(jù)
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# print(q.get(True, 5))
多線程爬蟲
分析:
爬蟲里面如何分多線程驴娃,
循環(huán):
拼接url,發(fā)送請(qǐng)求循集,獲取響應(yīng)
解析響應(yīng)唇敞,保存到文件
涉及到:
采集線程,3個(gè)線程同時(shí)采集
解析線程,3個(gè)線程同時(shí)解析
頁碼隊(duì)列:里面是要爬取的頁碼數(shù)據(jù)
數(shù)據(jù)隊(duì)列:采集線程向隊(duì)列中添加數(shù)據(jù)
解析線程從隊(duì)列中獲取數(shù)據(jù)
保存到同一個(gè)文件中疆柔,鎖機(jī)制
import threading
from queue import Queue
import time
from lxml import etree
import requests
import json
class CrawlThread(threading.Thread):
def __init__(self, name, page_queue, data_queue):
super().__init__()
self.name = name
# 保存頁碼隊(duì)列
self.page_queue = page_queue
self.data_queue = data_queue
# url
self.url = 'http://www.fanjian.net/duanzi-{}'
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
def run(self):
print('%s線程開始啟動(dòng)' % self.name)
# 這里面的思路是什么咒精?
while 1:
if self.page_queue.empty():
break
# 1、從頁碼隊(duì)列中獲取頁碼
page = self.page_queue.get()
# 2旷档、將url和頁碼進(jìn)行拼接
url = self.url.format(page)
# 3模叙、發(fā)送請(qǐng)求,獲取響應(yīng)
r = requests.get(url=url, headers=self.headers)
time.sleep(1)
# 4彬犯、將響應(yīng)內(nèi)容放入到數(shù)據(jù)隊(duì)列中
self.data_queue.put(r.text)
print('%s線程結(jié)束' % self.name)
class ParseThread(threading.Thread):
def __init__(self, name, data_queue, lock, fp):
super().__init__()
self.name = name
# 保存數(shù)據(jù)隊(duì)列
self.data_queue = data_queue
self.lock = lock
self.fp = fp
def run(self):
print('%s線程開始啟動(dòng)' % self.name)
# 解析線程解析步驟
while 1:
if self.data_queue.empty():
break
# 1向楼、從數(shù)據(jù)隊(duì)列中取出一個(gè)數(shù)據(jù)
content = self.data_queue.get()
# 2、解析這個(gè)數(shù)據(jù)
items = self.parse_content(content)
# 3谐区、寫入到文件中
string = json.dumps(items, ensure_ascii=False)
# 加鎖
self.lock.acquire()
self.fp.write(string)
# 釋放鎖
self.lock.release()
print('%s線程結(jié)束' % self.name)
# 解析數(shù)據(jù)函數(shù)
def parse_content(content):
# 生成tree對(duì)象
tree = etree.HTML(content)
# 先找到所有的li標(biāo)簽
li_list = tree.xpath('//li[@class="cont-item"]')
items = []
for oli in li_list:
# 獲取頭像
face = oli.xpath('.//div[@class="cont-list-reward"]//img/@data-src')[0]
# 獲取名字
name = oli.xpath('.//div[@class="cont-list-head"]/a/text()')[0]
# 獲取內(nèi)容
text = oli.xpath('.//div[@class="cont-list-main"]/p/text()')[0]
# 獲取時(shí)間
shijian = oli.xpath('.//div[@class="cont-list-info fc-gray"]/text()')[-1]
item = {
'頭像': face,
'名字': name,
'內(nèi)容': text,
'時(shí)間': shijian,
}
# 將字典添加到列表中
items.append(item)
return items
def create_queue():
page_queue = Queue()
data_queue = Queue()
# 向頁碼隊(duì)列中添加頁碼
for page in range(1, 11):
page_queue.put(page)
return page_queue, data_queue
def main():
# 做什么湖蜕?
# 創(chuàng)建鎖
lock = threading.Lock()
# 打開文件
fp = open('duanzi.txt', 'w', encoding='utf8')
# 創(chuàng)建兩個(gè)隊(duì)列
page_queue, data_queue = create_queue()
# 創(chuàng)建采集、解析線程
crawlname_list = ['采集線程1', '采集線程2', '采集線程3']
parsename_list = ['解析線程1', '解析線程2', '解析線程3']
# 列表宋列,用來保存所有的采集線程和解析線程
t_crawl_list = []
t_parse_list = []
for crawlname in crawlname_list:
t_crawl = CrawlThread(crawlname, page_queue, data_queue)
t_crawl.start()
# 將對(duì)應(yīng)的采集線程保存起來
t_crawl_list.append(t_crawl)
for parsename in parsename_list:
t_parse = ParseThread(parsename, data_queue, lock, fp)
# 將對(duì)應(yīng)的解析線程保存起來
t_parse_list.append(t_parse)
t_parse.start()
# 讓主線程等待子線程結(jié)束之后再結(jié)束
for t_crawl in t_crawl_list:
t_crawl.join()
for t_parse in t_parse_list:
t_parse.join()
fp.close()
print('主線程昭抒、子線程全部結(jié)束')
if __name__ == '__main__':
main()
# 留給大家了,為什么里面沒有寫數(shù)據(jù)呢炼杖?
自動(dòng)識(shí)別驗(yàn)證碼
(1)光學(xué)識(shí)別 OCR 其實(shí)就是一個(gè)軟件
- 別對(duì)他期望太高灭返,識(shí)別率80% 90%
*訓(xùn)練它
代碼識(shí)別
pip install pytesseract
pip install pillow
轉(zhuǎn)化為灰度圖片
img = img.convert('L')
img.show()
二值化處理
threshold = 140
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
out = img.point(table, '1')
out.show()
img = img.convert('RGB')
enhancer = ImageEnhance.Color(img)
enhancer = enhancer.enhance(0)
enhancer = ImageEnhance.Brightness(enhancer)
enhancer = enhancer.enhance(2)
enhancer = ImageEnhance.Contrast(enhancer)
enhancer = enhancer.enhance(8)
enhancer = ImageEnhance.Sharpness(enhancer)
img = enhancer.enhance(20)
實(shí)例代碼如下
import pytesseract
from PIL import Image
from PIL import ImageEnhance
def shibie(imagepath):
img = Image.open(imagepath)
img = img.convert('RGB')
enhancer = ImageEnhance.Color(img)
enhancer = enhancer.enhance(0)
enhancer = ImageEnhance.Brightness(enhancer)
enhancer = enhancer.enhance(2)
enhancer = ImageEnhance.Contrast(enhancer)
enhancer = enhancer.enhance(8)
enhancer = ImageEnhance.Sharpness(enhancer)
img = enhancer.enhance(20)
# 轉(zhuǎn)化為灰度圖片
img = img.convert('L')
# img.show()
# 二值化處理
threshold = 140
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
out = img.point(table, '1')
# out.show()
img = img.convert('RGB')
return pytesseract.image_to_string(img)
shibie('code.png')
打碼平臺(tái),專業(yè)坤邪,識(shí)別率高熙含,花錢
云打碼平臺(tái)使用
用戶注冊(cè)(充錢)、開發(fā)者注冊(cè)(創(chuàng)建應(yīng)用艇纺,使用應(yīng)用識(shí)別驗(yàn)證碼服務(wù))
import http.client, mimetypes, urllib, json, time, requests
######################################################################
class YDMHttp:
apiurl = 'http://api.yundama.com/api.php'
username = ''
password = ''
appid = ''
appkey = ''
def __init__(self, username, password, appid, appkey):
self.username = username
self.password = password
self.appid = str(appid)
self.appkey = appkey
def request(self, fields, files=[]):
response = self.post_url(self.apiurl, fields, files)
response = json.loads(response)
return response
def balance(self):
data = {'method': 'balance', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey}
response = self.request(data)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['balance']
else:
return -9001
def login(self):
data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey}
response = self.request(data)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['uid']
else:
return -9001
def upload(self, filename, codetype, timeout):
data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'codetype': str(codetype), 'timeout': str(timeout)}
file = {'file': filename}
response = self.request(data, file)
if (response):
if (response['ret'] and response['ret'] < 0):
return response['ret']
else:
return response['cid']
else:
return -9001
def result(self, cid):
data = {'method': 'result', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'cid': str(cid)}
response = self.request(data)
return response and response['text'] or ''
def decode(self, filename, codetype, timeout):
cid = self.upload(filename, codetype, timeout)
if (cid > 0):
for i in range(0, timeout):
result = self.result(cid)
if (result != ''):
return cid, result
else:
time.sleep(1)
return -3003, ''
else:
return cid, ''
def report(self, cid):
data = {'method': 'report', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'cid': str(cid), 'flag': '0'}
response = self.request(data)
if (response):
return response['ret']
else:
return -9001
def post_url(self, url, fields, files=[]):
for key in files:
files[key] = open(files[key], 'rb');
res = requests.post(url, files=files, data=fields)
return res.text
######################################################################
# 用戶名
# 普通賬號(hào)的用戶名
username = ''
# 密碼
# 普通賬號(hào)的密碼
password = ''
# 軟件ID怎静,開發(fā)者分成必要參數(shù)。登錄開發(fā)者后臺(tái)【我的軟件】獲得黔衡!
appid =
# 軟件密鑰蚓聘,開發(fā)者分成必要參數(shù)。登錄開發(fā)者后臺(tái)【我的軟件】獲得盟劫!
appkey = ''
# 圖片文件
filename = './png/e6ay.png'
# 驗(yàn)證碼類型夜牡,# 例:1004表示4位字母數(shù)字,不同類型收費(fèi)不同侣签。請(qǐng)準(zhǔn)確填寫塘装,否則影響識(shí)別率。在此查詢所有類型 http://www.yundama.com/price.html
codetype = 1004
# 超時(shí)時(shí)間影所,秒
timeout = 60
# 檢查
if (username == 'username'):
print('請(qǐng)?jiān)O(shè)置好相關(guān)參數(shù)再測(cè)試')
else:
# 初始化
yundama = YDMHttp(username, password, appid, appkey)
# 登陸云打碼
uid = yundama.login();
print('uid: %s' % uid)
# 查詢余額
balance = yundama.balance();
print('balance: %s' % balance)
# 開始識(shí)別氢哮,圖片路徑,驗(yàn)證碼類型ID型檀,超時(shí)時(shí)間(秒),識(shí)別結(jié)果
cid, result = yundama.decode(filename, codetype, timeout);
print('cid: %s, result: %s' % (cid, result))
######################################################################