小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

爬蟲(chóng)精進(jìn)6

 ZJ我的360帳號(hào) 2021-01-24

—————————如有疑問(wèn),歡迎交流指正————————

第6關(guān)

練習(xí)-儲(chǔ)存電影信息-參考

第一步:分析問(wèn)題,明確結(jié)果

問(wèn)題需求就是把豆瓣TOP250里面的 序號(hào)/電影名/評(píng)分/推薦語(yǔ)/鏈接 都爬取下來(lái),結(jié)果是存儲(chǔ)在csv和Excel中

【講解】

問(wèn)題需求就是把豆瓣TOP250里面的 序號(hào)/電影名/評(píng)分/推薦語(yǔ)/鏈接 都爬取下來(lái),結(jié)果是存儲(chǔ)在csv和Excel中

這里拓展一下如何取標(biāo)簽???~

https:///docs/QWQJYGw8CtcwQwyq/ 《豆瓣250爬蟲(chóng)思路詳解》

第二步:書(shū)寫(xiě)爬蟲(chóng)代碼

回顧下第三關(guān)的爬蟲(chóng)代碼

【解答】

選擇語(yǔ)言
import requests,bs4

for x in range(10):
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
url = 'https://movie.douban.com/top250?start=' + str(x*25) + '&filter='
res = requests.get(url,headers=headers)
bs = bs4.BeautifulSoup(res.text, 'html.parser')
bs = bs.find('ol', class_='grid_view')
for titles in bs.find_all('li'):
num = titles.find('em',class_='').text
title = titles.find('span', class_='title').text
comment = titles.find('span',class_='rating_num').text
url_movie = titles.find('a')['href']
if titles.find('span',class_='inq') != None:
tes = titles.find('span',class_='inq').text
print(num + '.' + title + '——' + comment + '\n' + '推薦語(yǔ):' + tes +'\n' + url_movie)
else:
print(num + '.' + title + '——' + comment + '\n' +'\n' + url_movie)

第三步: 完善代碼,用Excel存儲(chǔ)信息

要存儲(chǔ)在Excel中呢,需要先創(chuàng)建工作表,重命名,再設(shè)置表頭,把爬取的信息寫(xiě)成列表,然后用append函數(shù)多行寫(xiě)入Excel,最后命名保存這個(gè)Excel 文件。

請(qǐng)改寫(xiě)下方的爬蟲(chóng)代碼,實(shí)現(xiàn)使用Excel存儲(chǔ)信息。

【解答】

選擇語(yǔ)言
import requests, bs4, openpyxl

wb=openpyxl.Workbook()
#創(chuàng)建工作薄
sheet=wb.active
#獲取工作薄的活動(dòng)表
sheet.title='movies'
#工作表重命名
sheet['A1'] ='序號(hào)' #加表頭,給A1單元格賦值
sheet['B1'] ='電影名' #加表頭,給B1單元格賦值
sheet['C1'] ='評(píng)分' #加表頭,給C1單元格賦值
sheet['D1'] ='推薦語(yǔ)' #加表頭,給D1單元格賦值
sheet['E1'] ='鏈接' #加表頭,給E1單元格賦值

for x in range(10):
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
url = 'https://movie.douban.com/top250?start=' + str(x*25) + '&filter='
res = requests.get(url,headers=headers)
bs = bs4.BeautifulSoup(res.text, 'html.parser')
bs = bs.find('ol', class_='grid_view')
for titles in bs.find_all('li'):
num = titles.find('em',class_='').text
title = titles.find('span', class_='title').text
comment = titles.find('span',class_='rating_num').text
url_movie = titles.find('a')['href']
if titles.find('span',class_='inq') != None:
tes = titles.find('span',class_='inq').text
sheet.append([num, title, comment, tes, url_movie])
# 把num, title, comment, tes和url_movie寫(xiě)成列表,用append函數(shù)多行寫(xiě)入Excel
print(num + '.' + title + '——' + comment + '\n' + '推薦語(yǔ):' + tes +'\n' + url_movie)
else:
sheet.append([num, title, comment, None,url_movie])
print(num + '.' + title + '——' + comment + '\n' +'\n' + url_movie)
wb.save('movieTop250.xlsx')
#最后保存并命名這個(gè)Excel文件

第四步:另辟蹊徑,用csv格式存儲(chǔ)信息

思考下如何用csv創(chuàng)建寫(xiě)入存儲(chǔ)呢?

請(qǐng)修改下方代碼,實(shí)現(xiàn)使用csv存儲(chǔ)信息。

【提示】

選擇語(yǔ)言
import requests, bs4, csv
#引用csv模塊。
csv_file=open('movieTop250.csv', 'w', newline='')
#調(diào)用open()函數(shù)打開(kāi)csv文件,傳入?yún)?shù):文件名“movieTop250.csv”、寫(xiě)入模式“w”、newline=''

【解答】

選擇語(yǔ)言
import requests, bs4, csv
#引用csv模塊。
csv_file=open('movieTop250.csv', 'w', newline='')
#調(diào)用open()函數(shù)打開(kāi)csv文件,傳入?yún)?shù):文件名“movieTop250.csv”、寫(xiě)入模式“w”、newline=''。
writer = csv.writer(csv_file)
# 用csv.writer()函數(shù)創(chuàng)建一個(gè)writer對(duì)象。
writer.writerow(['序號(hào)', '電影名', '評(píng)分', '推薦語(yǔ)', '鏈接'])
#調(diào)用writer對(duì)象的writerow()方法,可以在csv文件里寫(xiě)入title:'序號(hào)', '電影名', '評(píng)分', '推薦語(yǔ)', '鏈接'

for x in range(10):
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
url = 'https://movie.douban.com/top250?start=' + str(x*25) + '&filter='
res = requests.get(url,headers=headers)
bs = bs4.BeautifulSoup(res.text, 'html.parser')
bs = bs.find('ol', class_='grid_view')
for titles in bs.find_all('li'):
num = titles.find('em',class_='').text
title = titles.find('span', class_='title').text
comment = titles.find('span',class_='rating_num').text
url_movie = titles.find('a')['href']
if titles.find('span',class_='inq') != None:
tes = titles.find('span',class_='inq').text
# 把num, title, comment, tes和url_movie寫(xiě)成列表,用append函數(shù)多行寫(xiě)入Excel
writer.writerow([num + '.' + title + '——' + comment + '\n' + '推薦語(yǔ):' + tes +'\n' + url_movie])
else:
writer.writerow([num + '.' + title + '——' + comment + '\n' +'\n' + url_movie])
csv_file.close()

記得出現(xiàn)亂碼的問(wèn)題,可以看這里的解決方法哦~

https:///docs/hqTrdqwQhCJGktWV/ 《爬蟲(chóng)第6關(guān)常見(jiàn)問(wèn)題解決方法》

第7關(guān)

練習(xí)-做個(gè)測(cè)單詞的小工具-參考

第一步:分析需求,明確目標(biāo)

扇貝網(wǎng):https://www./已經(jīng)有一個(gè)測(cè)單詞量的功能,我們要做的就是把這個(gè)功能復(fù)制下來(lái),并且做點(diǎn)改良,搞一個(gè)網(wǎng)頁(yè)版沒(méi)有的功能 ———— 自動(dòng)生成錯(cuò)詞本。

在這一步,請(qǐng)閱讀文檔的同時(shí)打開(kāi)瀏覽器的扇貝網(wǎng),跟著我一步步來(lái)。

【提示】

這里是扇貝網(wǎng)的測(cè)單詞量的界面:

??

想要復(fù)制功能,就先做分析,這個(gè)網(wǎng)頁(yè)是怎樣的工作流程。

所以,先體驗(yàn)全程,大概分為如下五個(gè)頁(yè)面:

??

??

??

??

??

先看源代碼里是否有我們的單詞。倘若有,就用find()/find_all()定位提取需要的數(shù)據(jù);

沒(méi)有的話,就要調(diào)用【檢查】-【Network】 - 【XHR】 - 找數(shù)據(jù)。

在Headers里看網(wǎng)址,在Preview里看內(nèi)容。

??

??

如圖:category/這一個(gè)XHR,用的是Get請(qǐng)求方式,訪問(wèn)了網(wǎng)址https://www./api/v1/vocabtest/category/,下載了一個(gè)字典。

其中“data”里面,藏了十個(gè)元素。這十個(gè)元素,里面對(duì)應(yīng)的內(nèi)容,就是我們最開(kāi)始要選擇的“詞匯范圍”。

十個(gè)元素,每個(gè)里面都有兩個(gè)內(nèi)容。0是什么暫時(shí)還不知道,先放著。1是我們?cè)~匯范圍沒(méi)錯(cuò)。

比如我們選擇高考,那么在第2個(gè)元素里就有一個(gè)0是“NCEE”,有一個(gè)1是“高考”。

我們接著看下一個(gè)XHR:

??

這個(gè)圖片說(shuō)明:?category=NCEE 這一個(gè)XHR,訪問(wèn)了網(wǎng)址https://www./api/v1/vocabtest/vocabularies/?category=NCEE

在此,“NCEE”出現(xiàn)了兩次:這個(gè)XHR的名字里面有“NCEE”,它訪問(wèn)的網(wǎng)址里面也有“NCEE”。

這就揭示了一種對(duì)應(yīng)關(guān)系:當(dāng)我們選擇“高考”詞庫(kù),那么下一個(gè)XHR,訪問(wèn)的網(wǎng)址就會(huì)是用“NCEE”來(lái)結(jié)尾。

可以多試幾個(gè)詞庫(kù)驗(yàn)證下我們的猜測(cè),的確里面的對(duì)應(yīng)關(guān)系是一致的??佳泻蚇GEE一組,四級(jí)和CET4一組,六級(jí)和CET6一組。

第1個(gè)XHR,所訪問(wèn)的網(wǎng)址規(guī)律就是:'https://www./api/v1/vocabtest/vocabularies/?category='+'你選擇的詞庫(kù),對(duì)應(yīng)的代碼'。

??

如圖,它下載到的是一個(gè)字典。字典里,包含了用來(lái)測(cè)試詞匯量的50個(gè)單詞。

第0,它先給出單詞。

第1,它給出四個(gè)不同的翻譯,每個(gè)翻譯都有一個(gè)對(duì)應(yīng)的pk值和rank值。

第2,它再給出一組pk值和rank值。它們,和正確翻譯里面的pk值與rank值一致。

那么,我們就可以理清楚,這個(gè)網(wǎng)頁(yè)的工作邏輯。如下圖:

??

到這里,我們就完成了至關(guān)重要的“需求分析”這個(gè)步驟。

第二步:分步講解,書(shū)寫(xiě)代碼 (??????) ?

??

【講解】

下面,我將帶你一步步完成代碼。

(0). 選擇題庫(kù)。

寫(xiě)這個(gè)程序,要用到requests模塊。

先用requests下載鏈接,再用res.json()解析下載內(nèi)容。

讓用戶選擇想測(cè)的詞庫(kù),輸入數(shù)字編號(hào),獲取題庫(kù)的代碼。

提示:記得給input前面加一個(gè)int()來(lái)轉(zhuǎn)換數(shù)據(jù)類型

【解答】

選擇語(yǔ)言
import requests

lin=requests.get('https://www./api/v1/vocabtest/category/')
#先用requests下載鏈接。
js_link = lin.json()
#解析下載得到的內(nèi)容。
bianhao = int(input('''請(qǐng)輸入你選擇的詞庫(kù)編號(hào),按Enter確認(rèn)
1,GMAT  2,考研  3,高考  4,四級(jí)  5,六級(jí)
6,英專  7,托福  8,GRE  9,雅思  10,任意
>'''))
#讓用戶選擇自己想測(cè)的詞庫(kù),輸入數(shù)字編號(hào)。int()來(lái)轉(zhuǎn)換數(shù)據(jù)類型
ciku = js_link['data'][bianhao-1][0]
print(ciku)

(1). 根據(jù)選擇的題庫(kù),獲取50個(gè)單詞。

第0步我們已經(jīng)拿到鏈接,這步直接用requests去下載,re.json()解析即可。

【解答】

選擇語(yǔ)言
test = requests.get('https://www./api/v1/vocabtest/vocabularies/?category='+ciku)
#下載用于測(cè)試的50個(gè)單詞。
words = test.json()
#對(duì)測(cè)試的單詞進(jìn)行解析。
print(words)

(2). 讓用戶選擇認(rèn)識(shí)的單詞:此處,要分別記錄下用戶認(rèn)識(shí)哪些,不認(rèn)識(shí)哪些。

已經(jīng)有了單詞數(shù)據(jù),提取出來(lái)讓用戶識(shí)別,并記錄用戶認(rèn)識(shí)哪些不認(rèn)識(shí)哪些,至少2個(gè)list來(lái)記錄。

50個(gè)單詞,記得要用循環(huán)。用戶手動(dòng)輸入自己的選擇,用input() 。我們要識(shí)別用戶的輸入,并基于此決定把這個(gè)單詞放進(jìn)哪個(gè)list,需要用if語(yǔ)句。

提示:當(dāng)一個(gè)元素特別長(zhǎng)的時(shí)候,給代碼多加一個(gè)list。

提示:加個(gè)換行,優(yōu)化用戶視角。

新增一個(gè)list,用于統(tǒng)計(jì)用戶認(rèn)識(shí)的單詞。

創(chuàng)建一個(gè)空的列表,用于記錄用戶認(rèn)識(shí)的單詞。

創(chuàng)建一個(gè)空的列表,用于記錄用戶不認(rèn)識(shí)的單詞。

啟動(dòng)一個(gè)循環(huán),循環(huán)的次數(shù)等于單詞的數(shù)量。

 如果用戶認(rèn)識(shí):就把這個(gè)單詞,追加進(jìn)列表words_knows。

否則,就把這個(gè)單詞,追加進(jìn)列表not_knows。

打印一個(gè)統(tǒng)計(jì)數(shù)據(jù):這么多單詞,認(rèn)識(shí)幾個(gè),認(rèn)識(shí)的有哪些?

【解答】

選擇語(yǔ)言
danci = []
#新增一個(gè)list,用于統(tǒng)計(jì)用戶認(rèn)識(shí)的單詞
words_knows = []
not_knows = []
print ('測(cè)試現(xiàn)在開(kāi)始。如果你認(rèn)識(shí)這個(gè)單詞,請(qǐng)輸入Y,否則直接敲Enter:')
n=0
for x in words['data']:
    n=n+1
    print ('\n第'+str(n)+'個(gè):'+x['content'])
    #加一個(gè)\n,用于換行。
    answer = input('認(rèn)識(shí)請(qǐng)敲Y,否則敲Enter:')
    if answer == 'Y':
        danci.append(x['content'])
        #把用戶認(rèn)識(shí)的單詞,追加進(jìn)danci這個(gè)list。
        words_knows.append(x)
    else:
        not_knows.append(x)

print ('\n在上述'+str(len(words['data']))+'個(gè)單詞當(dāng)中,有'+str(len(danci))+'個(gè)是你覺(jué)得自己認(rèn)識(shí)的,它們是:')
print(danci)

(3). 對(duì)于用戶認(rèn)識(shí)的單詞,給選擇題讓用戶做:此處要記錄用戶做對(duì)了哪些,做錯(cuò)了哪些。

這一步是第0步和第2步的組合——涉及到第0步中的選擇,也涉及到第2步的數(shù)據(jù)記錄。

提示: 面對(duì)冗長(zhǎng)的字典列表相互嵌套,可以創(chuàng)建字典。

【解答】

選擇語(yǔ)言
print ('現(xiàn)在我們來(lái)檢測(cè)一下,你有沒(méi)有真正掌握它們:')
wrong_words = []
right_num = 0
for y in words_knows:
    print('\n\n'+'A:'+y['definition_choices'][0]['definition'])
    #我們改用A、B、C、D,不再用rank值,下同
    print('B:'+y['definition_choices'][1]['definition'])
    print('C:'+y['definition_choices'][2]['definition'])
    print('D:'+y['definition_choices'][3]['definition'])
    xuanze = input('請(qǐng)選擇單詞\''+y['content']+'\'的正確翻譯:')
    dic = {'A':y['definition_choices'][0]['rank'],'B':y['definition_choices'][1]['rank'],'C':y['definition_choices'][2]['rank'],'D':y['definition_choices'][3]['rank']} 
    #我們創(chuàng)建一個(gè)字典,搭建起A、B、C、D和四個(gè)rank值的映射關(guān)系。
    if dic[xuanze] == y['rank']:
    #此時(shí)dic[xuanze]的內(nèi)容,其實(shí)就是rank值,此時(shí)的代碼含義已經(jīng)和之前的版本相同了。
        right_num += 1
    else:
        wrong_words.append(y)

(4). 生成報(bào)告:50個(gè)單詞,不認(rèn)識(shí)多少,認(rèn)識(shí)多少,掌握多少,錯(cuò)了多少。

生成報(bào)告主要有三部分:第0,是輸出統(tǒng)計(jì)數(shù)據(jù);第1,是打印錯(cuò)題集;第2,是把錯(cuò)題集保存到本地。

【解答】

選擇語(yǔ)言
import requests

link = requests.get('https://www./api/v1/vocabtest/category/')
#先用requests下載鏈接。
js_link = link.json()
#解析下載得到的內(nèi)容。
bianhao = int(input('''請(qǐng)輸入你選擇的詞庫(kù)編號(hào),按Enter確認(rèn)
1,GMAT  2,考研  3,高考  4,四級(jí)  5,六級(jí)
6,英專  7,托福  8,GRE  9,雅思  10,任意
>'''))
#讓用戶選擇自己想測(cè)的詞庫(kù),輸入數(shù)字編號(hào)。int()來(lái)轉(zhuǎn)換數(shù)據(jù)類型
ciku = js_link['data'][bianhao-1][0]
#利用用戶輸入的數(shù)字編號(hào),獲取題庫(kù)的代碼。如果以輸入“高考”的編號(hào)“3”為例,那么ciku的值就是,在字典js_link中查找data的值,data是一個(gè)list,查找它的第bianhao-1,也就是第2個(gè)元素,得到的依然是一個(gè)list,再查找該list的第0個(gè)元素。最后得到的就是我們想要的NCEE。
test = requests.get('https://www./api/v1/vocabtest/vocabularies/?category='+ciku)
#下載用于測(cè)試的50個(gè)單詞。
words = test.json()
#對(duì)test進(jìn)行解析。
danci = []
#新增一個(gè)list,用于統(tǒng)計(jì)用戶認(rèn)識(shí)的單詞
words_knows = []
#創(chuàng)建一個(gè)空的列表,用于記錄用戶認(rèn)識(shí)的單詞。
not_knows = []
#創(chuàng)建一個(gè)空的列表,用于記錄用戶不認(rèn)識(shí)的單詞。
print ('測(cè)試現(xiàn)在開(kāi)始。如果你認(rèn)識(shí)這個(gè)單詞,請(qǐng)輸入Y,否則直接敲Enter:')
n=0
for x in words['data']:
#啟動(dòng)一個(gè)循環(huán),循環(huán)的次數(shù)等于單詞的數(shù)量。
    n=n+1
    print ('\n第'+str(n)+'個(gè):'+x['content'])
    #加一個(gè)\n,用于換行。
    answer = input('認(rèn)識(shí)請(qǐng)敲Y,否則敲Enter:')
    #讓用戶輸入自己是否認(rèn)識(shí)。
    if answer == 'Y':
    #如果用戶認(rèn)識(shí):
        danci.append(x['content'])
        words_knows.append(x)
        #就把這個(gè)單詞,追加進(jìn)列表words_knows。
    else:
    #否則
        not_knows.append(x)
        #就把這個(gè)單詞,追加進(jìn)列表not_knows。

print ('\n在上述'+str(len(words['data']))+'個(gè)單詞當(dāng)中,有'+str(len(danci))+'個(gè)是你覺(jué)得自己認(rèn)識(shí)的,它們是:')
print(danci)

print ('現(xiàn)在我們來(lái)檢測(cè)一下,你有沒(méi)有真正掌握它們:')
wrong_words = []
right_num = 0
for y in words_knows:
    print('\n\n'+'A:'+y['definition_choices'][0]['definition'])
    #我們改用A、B、C、D,不再用rank值,下同
    print('B:'+y['definition_choices'][1]['definition'])
    print('C:'+y['definition_choices'][2]['definition'])
    print('D:'+y['definition_choices'][3]['definition'])
    xuanze = input('請(qǐng)選擇單詞\''+y['content']+'\'的正確翻譯(填寫(xiě)數(shù)字即可):')
    dic = {'A':y['definition_choices'][0]['rank'],'B':y['definition_choices'][1]['rank'],'C':y['definition_choices'][2]['rank'],'D':y['definition_choices'][3]['rank']} 
    #我們創(chuàng)建一個(gè)字典,搭建起A、B、C、D和四個(gè)rank值的映射關(guān)系。
    if dic[xuanze] == y['rank']:
    #此時(shí)dic[xuanze]的內(nèi)容,其實(shí)就是rank值,此時(shí)的代碼含義已經(jīng)和之前的版本相同了。
        right_num += 1
    else:
        wrong_words.append(y)

print ('現(xiàn)在,到了公布成績(jī)的時(shí)刻:')
print ('在'+str(len(words['data']))+'個(gè)'+js_link['data'][bianhao-1][1]+'詞匯當(dāng)中,你認(rèn)識(shí)其中'+str(len(danci))+'個(gè),實(shí)際掌握'+str(right_num)+'個(gè),錯(cuò)誤'+str(len(wrong_words))+'個(gè)。')
#這是句蠻復(fù)雜的話,對(duì)照前面的代碼和json文件你才能理解它。一個(gè)運(yùn)行示例是:在50個(gè)高考詞匯當(dāng)中,你認(rèn)識(shí)其中30個(gè),實(shí)際掌握25個(gè),錯(cuò)誤5個(gè)。

save = input ('是否打印并保存你的錯(cuò)詞集?填入Y或N: ')
#詢問(wèn)用戶,是否要打印并保存錯(cuò)題集。
if save == 'Y':
#如果用戶說(shuō)是:
    f = open('錯(cuò)題集.txt', 'a+')
    #在當(dāng)前目錄下,創(chuàng)建一個(gè)錯(cuò)題集.txt的文檔。        
    print ('你記錯(cuò)的單詞有:')
    f.write('你記錯(cuò)的單詞有:\n')
    #寫(xiě)入'你記錯(cuò)的單詞有:\n'
    m=0
    for z in wrong_words:
    #啟動(dòng)一個(gè)循環(huán),循環(huán)的次數(shù)等于,用戶的錯(cuò)詞數(shù):
        m=m+1
        print (z['content'])
        #打印每一個(gè)錯(cuò)詞。
        f.write(str(m+1) +'. '+ z['content']+'\n')
        #寫(xiě)入序號(hào),寫(xiě)入錯(cuò)詞。           
    print ('你不認(rèn)識(shí)的單詞有:')
    f.write('你沒(méi)記住的單詞有:\n')
    #寫(xiě)入'你沒(méi)記住的單詞有:\n'
    s=0
    for x in not_knows:
    #啟動(dòng)一個(gè)循環(huán),循環(huán)的次數(shù)等于,用戶不認(rèn)識(shí)的單詞數(shù)。
        print (x['content'])
        #打印每一個(gè)不認(rèn)識(shí)的單詞。
        f.write(str(s+1) +'. '+ x['content']+'\n')
        #寫(xiě)入序號(hào),寫(xiě)入用戶不認(rèn)識(shí)的詞匯。 
    print ('錯(cuò)詞和沒(méi)記住的詞已保存至當(dāng)前文件目錄下,下次見(jiàn)!')
    #告訴用戶,文件已經(jīng)保存好。
    #在網(wǎng)頁(yè)版終端運(yùn)行時(shí),文件會(huì)被寫(xiě)在課程的服務(wù)器上,你看不到,但它的確已經(jīng)存在。
else:
#如果用戶不想保存:
    print('下次見(jiàn)!')
    #輸出“下次見(jiàn)!”

三步:參考答案

參考答案

選擇語(yǔ)言
import requests

link = requests.get('https://www./api/v1/vocabtest/category/')
#先用requests下載鏈接。
js_link = link.json()
#解析下載得到的內(nèi)容。
bianhao = int(input('''請(qǐng)輸入你選擇的詞庫(kù)編號(hào),按Enter確認(rèn)
1,GMAT  2,考研  3,高考  4,四級(jí)  5,六級(jí)
6,英專  7,托福  8,GRE  9,雅思  10,任意
>'''))
#讓用戶選擇自己想測(cè)的詞庫(kù),輸入數(shù)字編號(hào)。int()來(lái)轉(zhuǎn)換數(shù)據(jù)類型
ciku = js_link['data'][bianhao-1][0]
#利用用戶輸入的數(shù)字編號(hào),獲取題庫(kù)的代碼。如果以輸入“高考”的編號(hào)“3”為例,那么ciku的值就是,在字典js_link中查找data的值,data是一個(gè)list,查找它的第bianhao-1,也就是第2個(gè)元素,得到的依然是一個(gè)list,再查找該list的第0個(gè)元素。最后得到的就是我們想要的NCEE。
test = requests.get('https://www./api/v1/vocabtest/vocabularies/?category='+ciku)
#下載用于測(cè)試的50個(gè)單詞。
words = test.json()
#對(duì)test進(jìn)行解析。
danci = []
#新增一個(gè)list,用于統(tǒng)計(jì)用戶認(rèn)識(shí)的單詞
words_knows = []
#創(chuàng)建一個(gè)空的列表,用于記錄用戶認(rèn)識(shí)的單詞。
not_knows = []
#創(chuàng)建一個(gè)空的列表,用于記錄用戶不認(rèn)識(shí)的單詞。
print ('測(cè)試現(xiàn)在開(kāi)始。如果你認(rèn)識(shí)這個(gè)單詞,請(qǐng)輸入Y,否則直接敲Enter:')
n=0
for x in words['data']:
#啟動(dòng)一個(gè)循環(huán),循環(huán)的次數(shù)等于單詞的數(shù)量。
    n=n+1
    print ('\n第'+str(n)+'個(gè):'+x['content'])
    #加一個(gè)\n,用于換行。
    answer = input('認(rèn)識(shí)請(qǐng)敲Y,否則敲Enter:')
    #讓用戶輸入自己是否認(rèn)識(shí)。
    if answer == 'Y':
    #如果用戶認(rèn)識(shí):
        danci.append(x['content'])
        words_knows.append(x)
        #就把這個(gè)單詞,追加進(jìn)列表words_knows。
    else:
    #否則
        not_knows.append(x)
        #就把這個(gè)單詞,追加進(jìn)列表not_knows。

print ('\n在上述'+str(len(words['data']))+'個(gè)單詞當(dāng)中,有'+str(len(danci))+'個(gè)是你覺(jué)得自己認(rèn)識(shí)的,它們是:')
print(danci)

print ('現(xiàn)在我們來(lái)檢測(cè)一下,你有沒(méi)有真正掌握它們:')
wrong_words = []
right_num = 0
for y in words_knows:
    print('\n\n'+'A:'+y['definition_choices'][0]['definition'])
    #我們改用A、B、C、D,不再用rank值,下同
    print('B:'+y['definition_choices'][1]['definition'])
    print('C:'+y['definition_choices'][2]['definition'])
    print('D:'+y['definition_choices'][3]['definition'])
    xuanze = input('請(qǐng)選擇單詞\''+y['content']+'\'的正確翻譯(填寫(xiě)數(shù)字即可):')
    dic = {'A':y['definition_choices'][0]['rank'],'B':y['definition_choices'][1]['rank'],'C':y['definition_choices'][2]['rank'],'D':y['definition_choices'][3]['rank']} 
    #我們創(chuàng)建一個(gè)字典,搭建起A、B、C、D和四個(gè)rank值的映射關(guān)系。
    if dic[xuanze] == y['rank']:
    #此時(shí)dic[xuanze]的內(nèi)容,其實(shí)就是rank值,此時(shí)的代碼含義已經(jīng)和之前的版本相同了。
        right_num += 1
    else:
        wrong_words.append(y)

print ('現(xiàn)在,到了公布成績(jī)的時(shí)刻:')
print ('在'+str(len(words['data']))+'個(gè)'+js_link['data'][bianhao-1][1]+'詞匯當(dāng)中,你認(rèn)識(shí)其中'+str(len(danci))+'個(gè),實(shí)際掌握'+str(right_num)+'個(gè),錯(cuò)誤'+str(len(wrong_words))+'個(gè)。')
#這是句蠻復(fù)雜的話,對(duì)照前面的代碼和json文件你才能理解它。一個(gè)運(yùn)行示例是:在50個(gè)高考詞匯當(dāng)中,你認(rèn)識(shí)其中30個(gè),實(shí)際掌握25個(gè),錯(cuò)誤5個(gè)。

save = input ('是否打印并保存你的錯(cuò)詞集?填入Y或N: ')
#詢問(wèn)用戶,是否要打印并保存錯(cuò)題集。
if save == 'Y':
#如果用戶說(shuō)是:
    f = open('錯(cuò)題集.txt', 'a+')
    #在當(dāng)前目錄下,創(chuàng)建一個(gè)錯(cuò)題集.txt的文檔。        
    print ('你記錯(cuò)的單詞有:')
    f.write('你記錯(cuò)的單詞有:\n')
    #寫(xiě)入'你記錯(cuò)的單詞有:\n'
    m=0
    for z in wrong_words:
    #啟動(dòng)一個(gè)循環(huán),循環(huán)的次數(shù)等于,用戶的錯(cuò)詞數(shù):
        m=m+1
        print (z['content'])
        #打印每一個(gè)錯(cuò)詞。
        f.write(str(m+1) +'. '+ z['content']+'\n')
        #寫(xiě)入序號(hào),寫(xiě)入錯(cuò)詞。           
    print ('你不認(rèn)識(shí)的單詞有:')
    f.write('你沒(méi)記住的單詞有:\n')
    #寫(xiě)入'你沒(méi)記住的單詞有:\n'
    s=0
    for x in not_knows:
    #啟動(dòng)一個(gè)循環(huán),循環(huán)的次數(shù)等于,用戶不認(rèn)識(shí)的單詞數(shù)。
        print (x['content'])
        #打印每一個(gè)不認(rèn)識(shí)的單詞。
        f.write(str(s+1) +'. '+ x['content']+'\n')
        #寫(xiě)入序號(hào),寫(xiě)入用戶不認(rèn)識(shí)的詞匯。 
    print ('錯(cuò)詞和沒(méi)記住的詞已保存至當(dāng)前文件目錄下,下次見(jiàn)!')
    #告訴用戶,文件已經(jīng)保存好。
    #在網(wǎng)頁(yè)版終端運(yùn)行時(shí),文件會(huì)被寫(xiě)在課程的服務(wù)器上,你看不到,但它的確已經(jīng)存在。
else:
#如果用戶不想保存:
    print('下次見(jiàn)!')
    #輸出“下次見(jiàn)!

第8關(guān)

練習(xí)-我家附近有啥好吃的-參考

項(xiàng)目目標(biāo):在本練習(xí),我們會(huì)借助cookies的相關(guān)知識(shí),使用Python登錄餓了么網(wǎng)站,爬取自己家附近的餐廳列表。

網(wǎng)站地址:https://www./home/

【講解】

在本練習(xí),我們會(huì)借助cookies的相關(guān)知識(shí),使用Python登錄餓了么網(wǎng)站,爬取自己家附近的餐廳。

網(wǎng)站地址:https://www./home/

想要順利地爬取餓了么上面的餐廳列表,我們需要先自己前往餓了么網(wǎng)站,手動(dòng)找到餐廳列表所在位置。然后,再用Python代碼去模擬這個(gè)過(guò)程。

首先,打開(kāi)餓了么首頁(yè):(https://www./home/)

打開(kāi)【檢查】工具,選擇【Network】,勾選【Preserve log】(因?yàn)榈葧?huì)可能會(huì)有頁(yè)面跳轉(zhuǎn),勾選上防止在跳轉(zhuǎn)過(guò)程中請(qǐng)求被清空)。

??

然后,輸入地址,如:“騰訊大廈”(推薦先把文字打好,再利用復(fù)制粘貼一次性輸入,不要一個(gè)字一個(gè)字填輸),頁(yè)面會(huì)彈出許多個(gè)地址給你選擇。此刻,會(huì)看到右側(cè)的Network面板里多出一個(gè)XHR:pois?……

這說(shuō)明,這些地址列表和XHR之間存在有對(duì)應(yīng)關(guān)系。記住這個(gè)XHR,它很重要,后面會(huì)用到。

我們先點(diǎn)擊一個(gè)地址,比如我選擇的第0個(gè),“騰訊大廈”,它會(huì)跳轉(zhuǎn)至一個(gè)新地址:(https://www./place/ws100xkkpznf?latitude=22.54055&longitude=113.934401)

??

時(shí),頁(yè)。點(diǎn)擊登錄,會(huì)來(lái)到(https://h5.ele.me/login/#redirect=https%3A%2F%2Fwww.%2Fplace%2Fws100xkkpznf%3Flatitude%3D22.54055%26longitude%3D113.934401)

??

閱讀該URL,很容易能夠看出這個(gè)是一個(gè)登錄頁(yè),因?yàn)橛衛(wèi)ogin存在。同時(shí)它在?之后所攜帶的參數(shù),含義是來(lái)源:我們剛剛從哪個(gè)URL跳轉(zhuǎn)過(guò)來(lái)。

輸入手機(jī)號(hào)碼,點(diǎn)擊收取驗(yàn)證碼,此時(shí)瀏覽器會(huì)發(fā)起請(qǐng)求:mobile_send_code。

手機(jī)收到驗(yàn)證碼,輸入驗(yàn)證碼,完成登錄。頁(yè)面會(huì)重新跳轉(zhuǎn)回我們剛剛來(lái)到的地址,此時(shí)的頁(yè)面,出現(xiàn)了我們想要的餐館名。

??

login_by_mobile即是登錄獲取cookies的那個(gè)請(qǐng)求。

通過(guò)翻找Network,我們定位到,存儲(chǔ)有餐廳列表的請(qǐng)求是XHR:restaurants…

該請(qǐng)求需要若干參數(shù),如下:

1. extras[]:activities

2. geohash:通過(guò)搜索得之,這是一個(gè)能夠代表地理位置的字符串。

3. latitude:緯度

4. limit:一次加載多少個(gè)餐館

5. longitude:經(jīng)度

6. offset:起始值

7. terminal: web

思考實(shí)現(xiàn)方案

這個(gè)網(wǎng)站,要求登錄才能實(shí)現(xiàn)爬取餐館列表。所以我們需要用到cookies來(lái)實(shí)現(xiàn)。

所以理論上,我們的代碼順序應(yīng)該是:模擬登錄獲取cookies,再帶著cookies去請(qǐng)求餐館列表。

不過(guò),必須要指出的是。請(qǐng)求餐館列表,還需要一些參數(shù)才行。這些參數(shù),和我們剛剛在首頁(yè)輸入“騰訊大廈”四個(gè)字的操作有關(guān)。

具體,我們?cè)谧龃a實(shí)操時(shí)再展開(kāi)講解。

所以正確的過(guò)程應(yīng)該是:

- 模擬登錄獲取cookies

- 模擬輸入“騰訊大廈”獲取必要的參數(shù)

- 帶著參數(shù)和cookies,去請(qǐng)求餐館列表

其中,前兩步可以順序調(diào)換。

【講解】

下面,我將帶你一步步完成代碼。

一、使用session和cookies模擬登錄

體驗(yàn)登錄:https://h5./login/

提示:此處需要先模擬發(fā)送驗(yàn)證碼的請(qǐng)求,再模擬登錄的請(qǐng)求。

提示:請(qǐng)求驗(yàn)證碼時(shí),會(huì)返回一個(gè)json,json里會(huì)有validate_token。它在我們輸入賬號(hào)驗(yàn)證碼模擬登錄的時(shí)候,會(huì)用到。

模擬登錄參考示例:

選擇語(yǔ)言
import requests
session = requests.session()
#創(chuàng)建會(huì)話。
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
#添加請(qǐng)求頭,避免被反爬蟲(chóng)。
url = ' https://wordpress-edu-3autumn.localprod./wp-login.php'
#登錄的網(wǎng)址。
data = {'log': input('請(qǐng)輸入你的賬號(hào):'),
'pwd': input('請(qǐng)輸入你的密碼:'),
'wp-submit': '登錄',
'redirect_to': 'https://wordpress-edu-3autumn.localprod./wp-admin/',
'testcookie': '1'}
#登錄的參數(shù)。
session.post(url, headers=headers, data=data)
#在會(huì)話下,用post發(fā)起登錄請(qǐng)求。

【解答】

選擇語(yǔ)言
import requests
session = requests.session()
# 創(chuàng)建會(huì)話
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
# 添加請(qǐng)求頭,避免被反爬蟲(chóng)
url_1 = 'https://h5./restapi/eus/login/mobile_send_code'
# 發(fā)送驗(yàn)證碼的網(wǎng)址
tel = input('請(qǐng)輸入手機(jī)號(hào)碼:')
data_1 = {'captcha_hash':'',
'captcha_value':'',
'mobile':tel,
'scf':''}
# 發(fā)送驗(yàn)證碼的參數(shù)
token = session.post(url_1, headers=headers, data=data_1).json()['validate_token']
# 在會(huì)話下,模擬獲取驗(yàn)證碼的請(qǐng)求

url_2 = 'https://h5./restapi/eus/login/login_by_mobile'
code = input('請(qǐng)輸入手機(jī)驗(yàn)證碼:')
data_2 = {'mobile':tel,
'scf':'ms',
'validate_code':code,
'validate_token':token}
session.post(url_2,headers=headers,data=data_2)

二、模擬輸入地址,獲取必要參數(shù)

為了請(qǐng)求餐館列表,我們需要幾個(gè)關(guān)鍵參數(shù):

1. geohash:通過(guò)搜索得之,這是一個(gè)能夠代表地理位置的字符串。

2. latitude:緯度

3. longitude:經(jīng)度

這三個(gè)參數(shù),都需要模擬輸入地址來(lái)獲得。請(qǐng)打印出這三個(gè)參數(shù)。

體驗(yàn)輸入地址:https://www./home/

提示:本步驟不需要模擬登錄

提示:在模擬該請(qǐng)求時(shí)需要用到城市的geohash值,可在XHR里查看自己城市的geohash值

【解答】

選擇語(yǔ)言
import requests
# 導(dǎo)入requests模塊。
address_url = 'https://www./restapi/v2/pois?'
# 你能夠在【Headers】-【General】里找到這個(gè)鏈接。
place = input('請(qǐng)輸入你的收貨地址:')
# 使用input輸入收獲地址,賦值給place。
# 因?yàn)槲覀兊膅eohash使用了深圳的值,所以推薦你測(cè)試的時(shí)候使用“騰訊大廈”。
params = {'extras[]':'count','geohash':'ws105rz9smwm','keyword':place,'limit':'20','type':'nearby'}
# 將要傳遞的參數(shù)封裝成字典,鍵與值都要用字符串,其中keyword對(duì)于的值是place。
address_res = requests.get(address_url,params=params)
# 發(fā)起請(qǐng)求,將響應(yīng)的結(jié)果,賦值給address_res
address_json = address_res.json()
# 將響應(yīng)的結(jié)果轉(zhuǎn)為列表/字典。

print('以下,是與'+place+'相關(guān)的位置信息:\n')
n=0
# 添加一個(gè)計(jì)數(shù)器,作為序號(hào)。
for address in address_json:
# 遍歷我們剛爬取的地址列表。
print(str(n)+'. '+address['name']+':'+address['short_address']+'\n')
# 打印序號(hào),地址名,短地址。
n = n+1
# 給計(jì)數(shù)器加1。
address_num = int(input('請(qǐng)輸入您選擇位置的序號(hào):'))
# 讓用戶選擇序號(hào)。
final_address = address_json[address_num]
# 確認(rèn)地址。

print(final_address['geohash'])
print(final_address['latitude'])
print(final_address['longitude'])

三、帶cookies和參數(shù)請(qǐng)求餐館列表

最后一步,將上述兩組代碼組合。

拿到cookies和參數(shù),完成請(qǐng)求餐館列表。

我?guī)湍泐A(yù)置了前兩個(gè)代碼,你可以在此基礎(chǔ)上完成本關(guān)卡任務(wù)。

【解答】

選擇語(yǔ)言
import requests
session = requests.session()

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
url_1 = 'https://h5./restapi/eus/login/mobile_send_code'
tel = input('請(qǐng)輸入手機(jī)號(hào)碼:')
data_1 = {'captcha_hash':'',
'captcha_value':'',
'mobile':tel,
'scf':''}

token = session.post(url_1, headers=headers, data=data_1).json()['validate_token']

url_2 = 'https://h5./restapi/eus/login/login_by_mobile'
code = input('請(qǐng)輸入手機(jī)驗(yàn)證碼:')
data_2 = {'mobile':tel,
'scf':'ms',
'validate_code':code,
'validate_token':token}

session.post(url_2,headers=headers,data=data_2)

address_url = 'https://www./restapi/v2/pois?'
place = input('請(qǐng)輸入你的收貨地址:')
params = {'extras[]':'count','geohash':'ws105rz9smwm','keyword':place,'limit':'20','type':'nearby'}
# 這里使用了深圳的geohash

address_res = requests.get(address_url,params=params)
address_json = address_res.json()

print('以下,是與'+place+'相關(guān)的位置信息:\n')
n=0
for address in address_json:
print(str(n)+'. '+address['name']+':'+address['short_address']+'\n')
n = n+1
address_num = int(input('請(qǐng)輸入您選擇位置的序號(hào):'))
final_address = address_json[address_num]

restaurants_url = 'https://www./restapi/shopping/restaurants?'
# 使用帶有餐館列表的那個(gè)XHR地址。
params = {'extras[]':'activities',
'geohash':final_address['geohash'],
'latitude':final_address['latitude'],
'limit':'24',
'longitude':final_address['longitude'],
'offset':'0',
'terminal':'web'
}
# 將參數(shù)封裝,其中g(shù)eohash和經(jīng)緯度,來(lái)自前面獲取到的數(shù)據(jù)。
restaurants_res = session.get(restaurants_url,params=params)
# 發(fā)起請(qǐng)求,將響應(yīng)的結(jié)果,賦值給restaurants_res
restaurants = restaurants_res.json()
# 把response對(duì)象,轉(zhuǎn)為json。
for restaurant in restaurants:
# restsurants最外層是一個(gè)列表,它可被遍歷。restaurant則是字典,里面包含了單個(gè)餐廳的所有信息。
print(restaurant['name'])

參考答案和總結(jié)

參考答案:

選擇語(yǔ)言
import requests
session = requests.session()

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
url_1 = 'https://h5./restapi/eus/login/mobile_send_code'
tel = input('請(qǐng)輸入手機(jī)號(hào)碼:')
data_1 = {'captcha_hash':'',
'captcha_value':'',
'mobile':tel,
'scf':''}

token = session.post(url_1, headers=headers, data=data_1).json()['validate_token']

url_2 = 'https://h5./restapi/eus/login/login_by_mobile'
code = input('請(qǐng)輸入手機(jī)驗(yàn)證碼:')
data_2 = {'mobile':tel,
'scf':'ms',
'validate_code':code,
'validate_token':token}

session.post(url_2,headers=headers,data=data_2)

address_url = 'https://www./restapi/v2/pois?'
place = input('請(qǐng)輸入你的收貨地址:')
params = {'extras[]':'count','geohash':'ws105rz9smwm','keyword':place,'limit':'20','type':'nearby'}
# 這里使用了深圳的geohash

address_res = requests.get(address_url,params=params)
address_json = address_res.json()

print('以下,是與'+place+'相關(guān)的位置信息:\n')
n=0
for address in address_json:
print(str(n)+'. '+address['name']+':'+address['short_address']+'\n')
n = n+1
address_num = int(input('請(qǐng)輸入您選擇位置的序號(hào):'))
final_address = address_json[address_num]

restaurants_url = 'https://www./restapi/shopping/restaurants?'
# 使用帶有餐館列表的那個(gè)XHR地址。
params = {'extras[]':'activities',
'geohash':final_address['geohash'],
'latitude':final_address['latitude'],
'limit':'24',
'longitude':final_address['longitude'],
'offset':'0',
'terminal':'web'
}
# 將參數(shù)封裝,其中g(shù)eohash和經(jīng)緯度,來(lái)自前面獲取到的數(shù)據(jù)。
restaurants_res = session.get(restaurants_url,params=params)
# 發(fā)起請(qǐng)求,將響應(yīng)的結(jié)果,賦值給restaurants_res
restaurants = restaurants_res.json()
# 把response對(duì)象,轉(zhuǎn)為json。
for restaurant in restaurants:
# restsurants最外層是一個(gè)列表,它可被遍歷。restaurant則是字典,里面包含了單個(gè)餐廳的所有信息。
print(restaurant['name'])

下面講一下會(huì)遇到的問(wèn)題~

validate_token這個(gè)在哪里可以找到呢?

??

輸入手機(jī)號(hào)碼,點(diǎn)擊獲取 驗(yàn)證碼后,在文件mobile_send_code的Preview里面

??

出現(xiàn)這樣的錯(cuò)誤keyerror:validate_token

或者:{'message': '賬戶存在風(fēng)險(xiǎn),需要圖形驗(yàn)證碼', 'name': 'NEED_CAPTCHA'}

??

出現(xiàn)這個(gè)問(wèn)題一般ip請(qǐng)求多次,一般第4次后,就可能引起餓了么的反爬機(jī)制,導(dǎo)致出現(xiàn)你的訪問(wèn)異常,結(jié)果是keyerror錯(cuò)誤;也就是需要圖形驗(yàn)證碼;

在山腰的知識(shí)暫時(shí)是無(wú)法解決的,目前可以每天嘗試幾次,或者換個(gè)手機(jī)或者ip網(wǎng)絡(luò);例如熱點(diǎn);建議出現(xiàn)keyerror可以暫時(shí)運(yùn)行跳過(guò),后續(xù)再試;一天一般有3-4次機(jī)會(huì)

如果要通過(guò)圖片驗(yàn)證,一般主流有4種方法:

1)打碼平臺(tái)付費(fèi)打碼

2)PIL庫(kù)提取圖片文字

3)第9關(guān)的selenium模擬

選擇語(yǔ)言
import requests
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'}
def get_picture():
url = 'https://h5./restapi/eus/v3/captchas'
param = {'captcha_str':input('手機(jī)號(hào)碼')}
res = requests.get(url,params=param).json()['captcha_image']
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(res)
time.sleep(5)

4)get_picture()

找到圖片驗(yàn)證碼在network里的位置,像爬圖片一樣保存到本地,然后input模擬輸入驗(yàn)證碼

(*在網(wǎng)頁(yè)中輸入手機(jī)號(hào),需要輸入驗(yàn)證碼,在network里的img里找到驗(yàn)證碼所在的圖片,在像第0關(guān)教的爬取圖片一樣爬到本地展示,在模擬input輸入)

選擇語(yǔ)言
import requests
url = 'https://h5./restapi/eus/v3/captchas'
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
'cookie': 'ubt_ssid=tita2xpcvoy6tbuzvwldp2tng4pz58l3_2019-04-28; _utrace=c2afcac7405b5632ba7a2987726b2cb4_2019-04-28; perf_ssid=e6xbec0ng906g0vof33vdf0vyrqgvts7_2019-04-28; UTUSER=0; cna=nawpFbIGrU8CAbcPsMlh4vqb; isg=BB0dLMZEHXmoNPlVLI0iBcyJLPkdMlOxf7IvI9_iInSjlj7Iq4jmXbNAwMo1VmlE',
}
captian = requests.get(url,headers=headers).json()
print(captian['captcha_image'])

補(bǔ)充:餓了么實(shí)現(xiàn)的參考博客

https://blog.csdn.net/weixin_43868179/article/details/94377658

餓了嗎里面那個(gè)查詢地址的鏈接是在哪找到的?

??

餓了么搜索地址的請(qǐng)求里url做了修改,練習(xí)時(shí)以網(wǎng)頁(yè)上實(shí)際的情況為準(zhǔn)

??

一份總結(jié):

就是這樣一個(gè)代碼,它能拿到給定位置附近的餐廳名。但它的潛力并不只是如此。

如果我們嘗試加載餓了么官網(wǎng)的首頁(yè),能夠找到一個(gè)xhr叫做cities,這個(gè)xhr里包含了全國(guó)兩千多個(gè)城市的經(jīng)緯度。

利用Python的geohash模塊,你可以將經(jīng)緯度數(shù)據(jù),轉(zhuǎn)化為geohash(當(dāng)然,也可以將geohash轉(zhuǎn)為經(jīng)緯度,我也是用這種方式,發(fā)現(xiàn)我的默認(rèn)geohash是深圳)。

那么在理論上,其實(shí)你可以通過(guò)這種方式,拿到全國(guó)餐廳的數(shù)據(jù)……

只要稍做擴(kuò)展,它還能拿到許多數(shù)據(jù):所有的餐廳名/電話號(hào)碼/評(píng)分/品牌/經(jīng)緯度/介紹/均價(jià)/月銷量……

此時(shí),這個(gè)爬蟲(chóng)就具備了商業(yè)價(jià)值,它能勝任許多數(shù)據(jù)分析的工作:選址策略、定價(jià)策略、差異化競(jìng)爭(zhēng)、2B營(yíng)銷……

或許你會(huì)質(zhì)疑自己能不能做到像我描述的這樣厲害,不用怕,很快你就能夠做到對(duì)此心中有數(shù)。

而在后續(xù)的關(guān)卡,當(dāng)你學(xué)會(huì)反爬蟲(chóng)的應(yīng)對(duì)策略、協(xié)程、Scrapy框架……你會(huì)變得像我說(shuō)的那樣強(qiáng)大。

新練習(xí)-大神快更文

??

困難(#fb5a5c)
cookies與session post與get json數(shù)據(jù)解析與提取 反爬蟲(chóng)應(yīng)對(duì)策略

要求:

在本練習(xí),我們會(huì)借助cookies的相關(guān)知識(shí),使用Python登錄小說(shuō)網(wǎng)站,用代碼的形式對(duì)熱榜上的大神進(jìn)行催更。

網(wǎng)站地址:https://www./

目的:

  1. 練習(xí)掌握cookies和session的用法
  1. 練習(xí)post和get請(qǐng)求
  1. 練習(xí)json數(shù)據(jù)的解析提取
  1. 反爬蟲(chóng)應(yīng)對(duì)策略

知識(shí)點(diǎn)回顧

cookies與session

cookies是服務(wù)器為了標(biāo)記用戶,存儲(chǔ)在用戶本地的數(shù)據(jù),它里面也保存了用戶的登錄信息,同時(shí)它有一定的時(shí)效性,過(guò)期就會(huì)失效。

??

session是會(huì)話過(guò)程中,服務(wù)器用來(lái)記錄特定用戶會(huì)話的信息。

??

session和cookies的關(guān)系:cookies里帶有session的編碼信息,服務(wù)器可以通過(guò)cookies辨別用戶,同時(shí)返回和這個(gè)用戶相關(guān)的特定編碼的session。

??

??

??

代碼示例如下: 

選擇語(yǔ)言
import requests,json
session = requests.session()
#創(chuàng)建會(huì)話。
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
#添加請(qǐng)求頭,避免被反爬蟲(chóng)。
try:
#如果能讀取到cookies文件,執(zhí)行以下代碼,跳過(guò)except的代碼,不用登錄就能發(fā)表評(píng)論。
cookies_txt = open('cookies.txt', 'r')
#以reader讀取模式,打開(kāi)名為cookies.txt的文件。
cookies_dict = json.loads(cookies_txt.read())
#調(diào)用json模塊的loads函數(shù),把字符串轉(zhuǎn)成字典。
cookies = requests.utils.cookiejar_from_dict(cookies_dict)
#把轉(zhuǎn)成字典的cookies再轉(zhuǎn)成cookies本來(lái)的格式。
session.cookies = cookies
#獲取會(huì)話下的cookies

except FileNotFoundError:
#如果讀取不到cookies文件,程序報(bào)“FileNotFoundError”(找不到文件)的錯(cuò),則執(zhí)行以下代碼,重新登錄獲取cookies,再評(píng)論。

url = 'https://wordpress-edu-3autumn.localprod.oc.forchange.cn/wp-login.php'
#登錄的網(wǎng)址。
data = {'log': input('請(qǐng)輸入你的賬號(hào):'),
'pwd': input('請(qǐng)輸入你的密碼:'),
'wp-submit': '登錄',
'redirect_to': 'https://wordpress-edu-3autumn.localprod./wp-admin/',
'testcookie': '1'}
#登錄的參數(shù)。
session.post(url, headers=headers, data=data)
#在會(huì)話下,用post發(fā)起登錄請(qǐng)求。

cookies_dict = requests.utils.dict_from_cookiejar(session.cookies)
#把cookies轉(zhuǎn)化成字典。
cookies_str = json.dumps(cookies_dict)
#調(diào)用json模塊的dump函數(shù),把cookies從字典再轉(zhuǎn)成字符串。
f = open('cookies.txt', 'w')
#創(chuàng)建名為cookies.txt的文件,以寫(xiě)入模式寫(xiě)入內(nèi)容
f.write(cookies_str)
#把已經(jīng)轉(zhuǎn)成字符串的cookies寫(xiě)入文件
f.close()
#關(guān)閉文件

url_1 = 'https://wordpress-edu-3autumn.localprod./wp-comments-post.php'
#文章的網(wǎng)址。
data_1 = {
'comment': input('請(qǐng)輸入你想評(píng)論的內(nèi)容:'),
'submit': '發(fā)表評(píng)論',
'comment_post_ID': '13',
'comment_parent': '0'
}
#評(píng)論的參數(shù)。
session.post(url_1, headers=headers, data=data_1)
#在會(huì)話下,用post發(fā)起評(píng)論請(qǐng)求。

post與get

post和get都可以帶著參數(shù)請(qǐng)求,不過(guò)get請(qǐng)求的參數(shù)會(huì)在url上顯示出來(lái)。但post請(qǐng)求的參數(shù)就不會(huì)直接顯示,而是隱藏起來(lái)。

在post請(qǐng)求里,我們使用data來(lái)傳遞參數(shù),其用法和params非常相像。

代碼示例:

選擇語(yǔ)言
import requests

url_1 = 'https://…'
headers = {'user-agent':''}
data = {}
# 定義url,headers和data

login_in = requests.post(url,headers=headers,data=data)
cookies = login_in.cookies
# 完成登錄,獲取cookies

url_2 = 'https://…'
params = {}
# 定義url和params

response = requests.get(url,headers=headers,params=params,cookies=cookies)
# 帶著cookies重新發(fā)起請(qǐng)求

步驟

題目要求

項(xiàng)目目標(biāo):在本練習(xí),我們會(huì)借助cookies的相關(guān)知識(shí),使用Python登錄小說(shuō)樓,爬取熱榜小說(shuō),對(duì)作者進(jìn)行催更。

網(wǎng)站地址:https://www./

【講解】

在本練習(xí),我們會(huì)借助cookies的相關(guān)知識(shí),使用Python登錄小說(shuō)樓,爬取熱榜小說(shuō),對(duì)作者進(jìn)行催更。

網(wǎng)站地址:https://www./

分步講解

在這一步,我會(huì)帶領(lǐng)你完成“分析過(guò)程”,請(qǐng)務(wù)必完整閱讀文檔。

在下一步,我們會(huì)開(kāi)始按步驟書(shū)寫(xiě)代碼。

【講解】

體驗(yàn)流程

想要對(duì)熱榜的小說(shuō)進(jìn)行催更,我們首先需要用瀏覽器體驗(yàn)這個(gè)過(guò)程。

前往小說(shuō)樓,手動(dòng)找到熱榜所在位置

  1. 隨機(jī)對(duì)一部小說(shuō)進(jìn)行催更
  1. 最后,再用Python代碼去模擬這個(gè)過(guò)程

進(jìn)入熱榜

首先,打開(kāi)小說(shuō)樓的排行榜頁(yè):https://www./top/allvisit_1/

打開(kāi)【檢查】工具,選擇【Network】,勾選【Preserve log】(因?yàn)榈葧?huì)可能會(huì)有頁(yè)面跳轉(zhuǎn),勾選上防止在跳轉(zhuǎn)過(guò)程中請(qǐng)求被清空)。 { 【新增圖片】

【原圖鏈接:】??

【原來(lái)的樣式:】??

【0】鼠標(biāo)右鍵選中下拉菜單的“檢查” 【1】選擇Network 【2】勾選Preserve log

??

體驗(yàn)登錄

1、然后我們可以隨機(jī)點(diǎn)擊其中一本小說(shuō),對(duì)其進(jìn)行催更 (現(xiàn)在網(wǎng)頁(yè)更新,已經(jīng)沒(méi)有催更功能了!建議同學(xué)們直接用下載小說(shuō)來(lái)做練習(xí))

??

??

2、此時(shí),如果沒(méi)有登錄小說(shuō)樓(或注冊(cè))的用戶,會(huì)自動(dòng)跳到小說(shuō)樓的登錄頁(yè)面:https://www./login.php

也就是說(shuō),想要催更,我們必須通過(guò)登錄呀~(模擬登陸?。?!催更的步驟先不做?。?/span>

??

3、閱讀該URL,很容易能夠看出這個(gè)是一個(gè)登錄頁(yè),因?yàn)橛墟溄佑袀€(gè)login(中文:登錄)

4、輸入賬號(hào)和密碼,同時(shí)查看Network,便會(huì)發(fā)現(xiàn)瀏覽器會(huì)攜帶著賬號(hào)和密碼發(fā)起Post請(qǐng)求。 { 【新增圖片】

【原圖鏈接:】??

??

獲取催更鏈接(換成下載小說(shuō)鏈接)

1、完成登錄之后,頁(yè)面會(huì)跳轉(zhuǎn)到催更的頁(yè)面,提示催更成功 ??

通過(guò)翻找Network,我們定位到,催更的請(qǐng)求是就是當(dāng)前的url:https://www./modules/article/usercui.php?id=xxx { 【新增圖片】

【原圖鏈接:】??

??

該請(qǐng)求只需要一個(gè)參數(shù):id(書(shū)籍的id)

注意:該鏈接限制了每天催更不能超過(guò)5次,也就是說(shuō)該鏈接的請(qǐng)求不能超過(guò)5次

獲取書(shū)籍id

1、進(jìn)入小說(shuō)熱門列表頁(yè)面:https://www./top/allvisit_1/右鍵檢查, 發(fā)現(xiàn)該頁(yè)面的數(shù)據(jù)就在第0個(gè)請(qǐng)求當(dāng)中。

2、模擬催更書(shū)籍《純陽(yáng)武神》時(shí),拿到的id是9356, 不過(guò)這個(gè)id到底從哪里來(lái)的? 要么,它藏在了HTML網(wǎng)頁(yè)當(dāng)中; 要么,它就是在請(qǐng)求的時(shí)候,后臺(tái)下發(fā)的。 可先在Elements搜索一下該id,看它在不在HTML里。 (【搜索快捷鍵】win:ctrl+f | mac:command+f) { 【新增圖片】

【原圖鏈接:】????

3、經(jīng)過(guò)分析,發(fā)現(xiàn)id確實(shí)藏在了HTML頁(yè)面的鏈接當(dāng)中:https://www./yuedu/9356/

4、下一步就是將數(shù)字9356從鏈接中分離出來(lái),方法有很多,老師這里只講解過(guò)濾器fliter過(guò)濾數(shù)字

選擇語(yǔ)言
link = 'https://www./yuedu/9356/'

# 字符串link過(guò)濾出數(shù)字id(9356)
id_list = list(filter(str.isdigit,link))
book_id = ''.join(book_id)

# 步驟解析:1、filter()過(guò)濾數(shù)字 2、filter對(duì)象轉(zhuǎn)列表 3、列表轉(zhuǎn)字符串
# filter(str.isdigit,字符串)
# 第一個(gè)參數(shù)用來(lái)判斷字符串的單個(gè)元素是否是數(shù)字,數(shù)字保留
# filter()返回的是對(duì)象,需要用list()函數(shù)轉(zhuǎn)換成列表
# ''.join(列表)將列表轉(zhuǎn)換成字符串

思考實(shí)現(xiàn)方案

所以正確的流程應(yīng)該是:

  • 模擬登錄獲取cookies
  • 拿到書(shū)籍的id
  • 使用id參數(shù)和cookies請(qǐng)求催更

注:其中,前兩步可以順序調(diào)換。

代碼實(shí)現(xiàn)

【講解】

下面,我將帶你一步步完成代碼。

一、使用session和cookies模擬登錄

體驗(yàn)登錄:https://www./login.php

模擬登錄參考示例:

選擇語(yǔ)言
import requests

# 創(chuàng)建會(huì)話。
session = requests.session()
# 添加請(qǐng)求頭,避免被反爬蟲(chóng)。
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}

# 登錄的網(wǎng)址。
url = ' https://wordpress-edu-3autumn.localprod.oc.forchange.cn/wp-login.php'
# 登錄的參數(shù)。
data = {'log': input('請(qǐng)輸入你的賬號(hào):'),
'pwd': input('請(qǐng)輸入你的密碼:'),
'wp-submit': '登錄',
'redirect_to': 'https://wordpress-edu-3autumn.localprod./wp-admin/',
'testcookie': '1'}

#在會(huì)話下,用post發(fā)起登錄請(qǐng)求。
session.post(url, headers=headers, data=data)

【代碼題】

【預(yù)設(shè)代碼】

# 小說(shuō)樓登錄請(qǐng)求:https://www./login.php

【解答】

選擇語(yǔ)言
import requests

# 創(chuàng)建會(huì)話
session = requests.session()
# 偽裝請(qǐng)求頭
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
# 登錄url
login_url = 'https://www./login.php'
# 登錄的參數(shù)。
data = {'username':input('請(qǐng)輸入你的賬號(hào):'),
'password':input('請(qǐng)輸入你的密碼:'),
'action':'login'}
result = session.post(login_url, headers=headers, data=data)

二、獲取書(shū)籍id

想要請(qǐng)求催更XHR,我們需要拿到參數(shù)id,也就是書(shū)籍id

小說(shuō)排行榜:https://www./top/allvisit_1/

提示1: 1. 本步驟不需要模擬登錄 2. 網(wǎng)站的編碼模式是gbk

提示2

選擇語(yǔ)言
link = 'https://www./yuedu/9356/'

# 字符串link過(guò)濾出數(shù)字id(9356)
id_list = list(filter(str.isdigit,link))
book_id = ''.join(book_id)

# 步驟解析:1、filter()過(guò)濾數(shù)字 2、filter對(duì)象轉(zhuǎn)列表 3、列表轉(zhuǎn)字符串
# filter(str.isdigit,字符串)
# 第一個(gè)參數(shù)用來(lái)判斷字符串的單個(gè)元素是否是數(shù)字,數(shù)字保留
# filter()返回的是對(duì)象,需要用list()函數(shù)轉(zhuǎn)換成列表
# ''.join(列表)將列表轉(zhuǎn)換成字符串

提示3:

選擇語(yǔ)言
# 爬取鏈接html頁(yè)面中a標(biāo)簽的鏈接以及內(nèi)容
import requests
from bs4 import BeautifulSoup

url = 'https://movie.douban.com/top250?start=25&filter='
results = requests.get(url)
results.encoding = 'utf8'
bs = BeautifulSoup(results.text,'html.parser')
ols = bs.find('ol',class_='grid_view')
for ls in ols.find_all('li'):
url_movie = ls.find('a')['href']
url_text = ls.find('a').text

【代碼題】

【預(yù)設(shè)代碼】

# 本步驟不需要模擬登錄

# 小說(shuō)樓的排行榜:https://www./top/allvisit_1/

【解答】

選擇語(yǔ)言

import requests
from bs4 import BeautifulSoup

hot_url = 'https://www./top/allvisit_1/'
r = requests.get(hot_url)
r.encoding = 'gbk'
bs = BeautifulSoup(r.text,'html.parser')
uls = bs.find_all('span',class_='up2')
books = {}
for li in uls:
book_name = li.find('a').text
link = li.find('a')['href']
id_list = list(filter(str.isdigit,link))
book_id = ''.join(id_list)
books[book_id] = book_name
print(books)

三、帶cookies和參數(shù)請(qǐng)求催更鏈接

將上述兩組代碼組合。

拿到cookies和參數(shù),完成催更請(qǐng)求(不要超過(guò)5次)

我?guī)湍泐A(yù)置了前兩個(gè)代碼,你可以在此基礎(chǔ)上完成本關(guān)卡任務(wù)。

注意: 1. 請(qǐng)求url需要拼接書(shū)籍id 2. 請(qǐng)求時(shí)候別忘了添加請(qǐng)求頭和cookies:cookies=session.cookies

【代碼題】

【預(yù)設(shè)代碼】

選擇語(yǔ)言
# 將上述兩組代碼組合。拿到cookies和參數(shù),完成催更請(qǐng)求。
# 我?guī)湍泐A(yù)置了前兩個(gè)代碼,你可以在此基礎(chǔ)上完成本關(guān)卡任務(wù)。

# 小說(shuō)樓:https://www./
# 小說(shuō)樓登錄:https://www./login.php
# 小說(shuō)樓的排行榜:https://www./top/allvisit_1/
# 小說(shuō)樓催更:https://www./modules/article/usercui.php?id=
import requests
from bs4 import BeautifulSoup

login_url = 'https://www./login.php'
hot_url = 'https://www./top/allvisit_1/'
urge_url = 'https://www./modules/article/usercui.php?id='
session = requests.session()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}

def login_cookies():
data = {'username':input('請(qǐng)輸入你的賬號(hào):'),
'password':input('請(qǐng)輸入你的密碼:'),
'action':'login'}
result = session.post(login_url, headers=headers, data=data)

def get_bookids():
result = requests.get(hot_url, headers=headers)
result.encoding = 'gbk'
bs = BeautifulSoup(result.text,'html.parser')
uls = bs.find_all('span',class_='up2')
books = {}
for li in uls:
book_name = li.find('a').text
link = li.find('a')['href']
id_list = list(filter(str.isdigit,link))
book_id = ''.join(id_list)
books[book_id] = book_name
return books

def urge(book_id):
# 請(qǐng)求催更鏈接需要拼接book_id
# 請(qǐng)求需要帶上headers和cookies

def main ():
login_cookies()
books = get_bookids()
print('--------熱門書(shū)籍--------')
for k,v in books.items():
print(k,':',v)
book_id = input('請(qǐng)輸入想要催更的書(shū)籍id:')
urge(book_id)
main()

【解答】

選擇語(yǔ)言
import requests
from bs4 import BeautifulSoup

login_url = 'https://www./login.php'
hot_url = 'https://www./top/allvisit_1/'
urge_url = 'https://www./modules/article/usercui.php?id='
session = requests.session()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}

def login_cookies():
data = {'username':input('請(qǐng)輸入你的賬號(hào):'),
'password':input('請(qǐng)輸入你的密碼:'),
'action':'login'}
result = session.post(login_url, headers=headers, data=data)

def get_bookids():
result = requests.get(hot_url, headers=headers)
result.encoding = 'gbk'
bs = BeautifulSoup(result.text,'html.parser')
uls = bs.find_all('span',class_='up2')
books = {}
for li in uls:
book_name = li.find('a').text
link = li.find('a')['href']
id_list = list(filter(str.isdigit,link))
book_id = ''.join(id_list)
books[book_id] = book_name
return books

def urge(book_id):

url = urge_url+book_id
result = session.get(url, headers=headers, cookies=session.cookies)
result.encoding = 'gbk'
if result.status_code == 200:
bs = BeautifulSoup(result.text,'html.parser')
urge_info = bs.find('div',class_='blocktitle').get_text()
urge_info2 = bs.find('div',class_='blockcontent').get_text()
print(urge_info)
print(urge_info2)

def main ():
login_cookies()
books = get_bookids()
print('--------熱門書(shū)籍--------')
for k,v in books.items():
print(k,':',v)
book_id = input('請(qǐng)輸入想要催更的書(shū)籍id:')
urge(book_id)
main()

參考答案和總結(jié)

【講解】

參考答案:

選擇語(yǔ)言
# 小說(shuō)樓:https://www./
# 小說(shuō)樓登錄:https://www./login.php
# 小說(shuō)樓的排行榜:https://www./top/allvisit_1/
# 小說(shuō)樓催更:https://www./modules/article/usercui.php?id=

import requests
from bs4 import BeautifulSoup

login_url = 'https://www./login.php'
hot_url = 'https://www./top/allvisit_1/'
urge_url = 'https://www./modules/article/usercui.php?id='
session = requests.session()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}

def login_cookies():
data = {'username':input('請(qǐng)輸入你的賬號(hào):'),
'password':input('請(qǐng)輸入你的密碼:'),
'action':'login'}
result = session.post(login_url, headers=headers, data=data)

def get_bookids():
result = requests.get(hot_url, headers=headers)
result.encoding = 'gbk'
bs = BeautifulSoup(result.text,'html.parser')
uls = bs.find_all('span',class_='up2')
books = {}
for li in uls:
book_name = li.find('a').text
link = li.find('a')['href']
id_list = list(filter(str.isdigit,link))
book_id = ''.join(id_list)
books[book_id] = book_name
return books

def urge(book_id):
url = urge_url+book_id
result = session.get(url, headers=headers, cookies=session.cookies)
result.encoding = 'gbk'
if result.status_code == 200:
bs = BeautifulSoup(result.text,'html.parser')
urge_info = bs.find('div',class_='blocktitle').get_text()
urge_info2 = bs.find('div',class_='blockcontent').get_text()
print(urge_info)
print(urge_info2)

def main ():
login_cookies()
books = get_bookids()
print('--------熱門書(shū)籍--------')
for k,v in books.items():
print(k,':',v)
book_id = input('請(qǐng)輸入想要催更的書(shū)籍id:')
urge(book_id)
main()

練習(xí)-自制翻譯器-參考

第一步:分析問(wèn)題,明確目標(biāo)

實(shí)現(xiàn)功能:用戶輸入英文或中文,程序即可打印出來(lái)對(duì)應(yīng)的譯文。

【講解】

我們?cè)谧筮呡斎胛淖?,那么瀏覽器會(huì)把輸入的信息傳輸給服務(wù)器,再返回對(duì)應(yīng)的內(nèi)容。

達(dá),來(lái)對(duì)應(yīng)文:

第二步:思考要用到的知識(shí)

【講解】

實(shí)現(xiàn)一鍵翻譯的功能,最簡(jiǎn)單的方案便是爬蟲(chóng)。在此,我們選擇的網(wǎng)站是有道翻譯。

你在左邊輸入文字,那么瀏覽器會(huì)把你輸入的信息傳輸給服務(wù)器。再返回對(duì)應(yīng)的內(nèi)容。

??

??

這就是一個(gè)典型的Post操作。

我們?cè)贖eaders也可以看到“Request Method: POST”哦~

??

在前幾關(guān)練習(xí)我們用的都是Get方式請(qǐng)求,Post是另一種常見(jiàn)的方式,課上已經(jīng)學(xué)過(guò)其用法,在此不多贅述。

__Get是向服務(wù)器發(fā)索取數(shù)據(jù)的一種請(qǐng)求,而Post是向服務(wù)器提交數(shù)據(jù)的一種請(qǐng)求__

雖然第八關(guān)我們主要講的是Cookies~

__Cookies用于服務(wù)器實(shí)現(xiàn)會(huì)話,用戶登錄及相關(guān)功能時(shí)進(jìn)行狀態(tài)管理__ 

但這道題并不需要用到小餅干,因?yàn)椴恍枰卿洸恍枰~號(hào)密碼等。

主要考查的還是Post的用法。

__注意哦__ ?(????)

有道翻譯有反爬蟲(chóng)機(jī)制,它使用了加密技術(shù)。如果你的程序報(bào)錯(cuò),你可以通過(guò)搜索、查閱資料找到解決方案:嘗試把訪問(wèn)的網(wǎng)址中“/translate_o”中的“_o”刪除。

服務(wù)器返回的內(nèi)容,是json的格式。我們可以用處理列表、處理字典的手段來(lái)提取翻譯。

第三步:寫(xiě)代碼

你可以在瀏覽器的[network]-[Headers]-[General]里找到需要訪問(wèn)的網(wǎng)址,在[network]-[Headers]-[From data]里找到需要上傳的數(shù)據(jù)。

__再次注意哦__ ?(????)

有道翻譯有反爬蟲(chóng)機(jī)制,它使用了加密技術(shù)。如果你的程序報(bào)錯(cuò),你可以通過(guò)搜索、查閱資料找到解決方案:嘗試把訪問(wèn)的網(wǎng)址中“/translate_o”中的“_o”刪除。

服務(wù)器返回的內(nèi)容,是json的格式。我們可以用處理列表、處理字典的手段來(lái)提取翻譯。

【解答】

選擇語(yǔ)言
import requests,json
#調(diào)用了兩個(gè)模塊。requests負(fù)責(zé)上傳和下載數(shù)據(jù),json負(fù)責(zé)解析。

word = input('你想翻譯什么呀?')
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
#使用post需要一個(gè)鏈接。
data={'i': word,
      'from': 'AUTO',
      'to': 'AUTO',
      'smartresult': 'dict',
      'client': 'fanyideskweb',
      'doctype': 'json',
      'version': '2.1',
      'keyfrom': 'fanyi.web',
      'action': 'FY_BY_REALTIME',
      'typoResult': 'false'}
#將需要post的內(nèi)容,以字典的形式記錄在data內(nèi)。
r = requests.post(url,data)
#post需要輸入兩個(gè)參數(shù),一個(gè)是剛才的鏈接,一個(gè)是data,返回的是一個(gè)Response對(duì)象。
answer=json.loads(r.text)
#你可以自己嘗試print一下r.text的內(nèi)容,然后再閱讀下面的代碼。
print ('翻譯的結(jié)果是:'+answer['translateResult'][0][0]['tgt'])

第四步:套層殼(小彩蛋,了解即可,感興趣的話可以深入學(xué)習(xí))

我們總會(huì)聽(tīng)到前端后端全棧,感覺(jué)神秘有高大上,你一定很好奇它們都是什么呀?

今天呢,我們就簡(jiǎn)單接觸下前端~

有米有很期待呀(?>???<‵)??

前端,是一種GUI軟件。而我們現(xiàn)在要用的是Python里的一個(gè)模塊實(shí)現(xiàn)本地窗口的功能。

它就是Tkinter~

Tkinter 模塊是 Python 的標(biāo)準(zhǔn) Tk GUI 工具包的接口。

Tk 和 Tkinter 可以在大多數(shù)的 Unix 平臺(tái)下使用,同樣可以應(yīng)用在 Windows 和 MacOS系統(tǒng)里。

Tk8.0 的后續(xù)版本可以實(shí)現(xiàn)本地窗口風(fēng)格,并良好地運(yùn)行在絕大多數(shù)平臺(tái)中。

http://www.runoob.com/python/python-gui-tkinter.html 

最后的代碼大約是這個(gè)模樣,注意閱讀注釋~

當(dāng)然你可以在終端運(yùn)行(復(fù)制)這些代碼,觀察效果~ 

【解答】

認(rèn)真閱讀注釋,你也可以復(fù)制下來(lái)在你的IDE中運(yùn)行下哦~ 

選擇語(yǔ)言
import requests
import json
from tkinter import Tk,Button,Entry,Label,Text,END

class YouDaoFanyi(object):
    def __init__(self):
        pass
    def crawl(self,word):
        url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
        #使用post需要一個(gè)鏈接
        data={'i': word,
              'from': 'AUTO',
              'to': 'AUTO',
              'smartresult': 'dict',
              'client': 'fanyideskweb',
              'doctype': 'json',
              'version': '2.1',
              'keyfrom': 'fanyi.web',
              'action': 'FY_BY_REALTIME',
              'typoResult': 'false'}
        #將需要post的內(nèi)容,以字典的形式記錄在data內(nèi)。
        r = requests.post(url, data)
        #post需要輸入兩個(gè)參數(shù),一個(gè)是剛才的鏈接,一個(gè)是data,返回的是一個(gè)Response對(duì)象
        answer=json.loads(r.text)
        #你可以自己嘗試print一下r.text的內(nèi)容,然后再閱讀下面的代碼。
        result = answer['translateResult'][0][0]['tgt']
        return result

class Application(object):
    def __init__(self):
        self.window = Tk()
        self.fanyi = YouDaoFanyi()
        self.window.title(u'我的翻譯')
        #設(shè)置窗口大小和位置
        self.window.geometry('310x370+500+300')
        self.window.minsize(310,370)
        self.window.maxsize(310,370)
        #創(chuàng)建一個(gè)文本框
        #self.entry = Entry(self.window)
        #self.entry.place(x=10,y=10,width=200,height=25)
        #self.entry.bind('<Key-Return>',self.submit1)
        self.result_text1 = Text(self.window,background = 'azure')
        # 喜歡什么背景色就在這里面找哦,但是有色差,得多試試:http://www.science./dftwiki/index.php/Color_Charts_for_TKinter
        self.result_text1.place(x = 10,y = 5,width = 285,height = 155)
        self.result_text1.bind('<Key-Return>',self.submit1)
        #創(chuàng)建一個(gè)按鈕
        #為按鈕添加事件
        self.submit_btn = Button(self.window,text=u'翻譯',command=self.submit)
        self.submit_btn.place(x=205,y=165,width=35,height=25)
        self.submit_btn2 = Button(self.window,text=u'清空',command = self.clean)
        self.submit_btn2.place(x=250,y=165,width=35,height=25)
        #翻譯結(jié)果標(biāo)題
        self.title_label = Label(self.window,text=u'翻譯結(jié)果:')
        self.title_label.place(x=10,y=165)
        #翻譯結(jié)果
        self.result_text = Text(self.window,background = 'light cyan')
        self.result_text.place(x = 10,y = 190,width = 285,height = 165)
        #回車翻譯
    def submit1(self,event):
        #從輸入框獲取用戶輸入的值
        content = self.result_text1.get(0.0,END).strip().replace('\n',' ')
        #把這個(gè)值傳送給服務(wù)器進(jìn)行翻譯
        result = self.fanyi.crawl(content)
        #將結(jié)果顯示在窗口中的文本框中
        self.result_text.delete(0.0,END)
        self.result_text.insert(END,result)
        #print(content)

    def submit(self):
        #從輸入框獲取用戶輸入的值
        content = self.result_text1.get(0.0,END).strip().replace('\n',' ')
        #把這個(gè)值傳送給服務(wù)器進(jìn)行翻譯
        result = self.fanyi.crawl(content)
        #將結(jié)果顯示在窗口中的文本框中
        self.result_text.delete(0.0,END)
        self.result_text.insert(END,result)
        print(content)

    #清空文本域中的內(nèi)容
    def clean(self):
        self.result_text1.delete(0.0,END)
        self.result_text.delete(0.0,END)

    def run(self):
        self.window.mainloop()

if __name__=='__main__':
    app = Application()
    app.run()

練習(xí)-圖靈機(jī)器人-參考

第一步:登錄注冊(cè)圖靈機(jī)器人

注冊(cè)登錄,才能創(chuàng)建自己的圖靈機(jī)器人。

根據(jù)幫助中心的“說(shuō)明書(shū)”,我們可以了解如何運(yùn)用這個(gè)新工具~

【講解】

進(jìn)入圖靈機(jī)器人官網(wǎng)[http://www./](http://www./),戳進(jìn)幫助中心。

??

就像打開(kāi)玩具先看說(shuō)明書(shū)一樣,我們來(lái)看看官方文檔怎么說(shuō)怎么用~ 

??

在功能說(shuō)明中,我們知道,首先得登錄注冊(cè),用免費(fèi)版本就可以了(當(dāng)然~土豪請(qǐng)隨意),創(chuàng)建機(jī)器人在“機(jī)器人設(shè)置”中,我們用的是第一個(gè)API接入

??

那什么是API呢?通俗地講:

__API就是接口__,就是通道,負(fù)責(zé)一個(gè)程序和其他軟件的溝通,本質(zhì)是預(yù)先定義的函數(shù),而我們不需要了解這個(gè)函數(shù)只是調(diào)用這個(gè)接口就可達(dá)到函數(shù)的效果。

好,接下來(lái)我們看下“API V2.0接入文檔”.

??

接口說(shuō)明:API接口可調(diào)用聊天對(duì)話、語(yǔ)料庫(kù)、技能三大模塊的語(yǔ)料。 

很好,我們今天想做的聊天機(jī)器人用這個(gè)接口就剛巧合適~ 

同時(shí),在使用說(shuō)明中我們可以知曉:

首先創(chuàng)建post請(qǐng)求所需的json數(shù)據(jù),然后向指定的接口發(fā)起post請(qǐng)求即可,而且從參數(shù)說(shuō)明中可以看到,只有參數(shù) perception 和 userinfo 才是必須的。

對(duì)于userid這個(gè)參數(shù)官方文檔說(shuō)的是:長(zhǎng)度小于32,是用戶的唯一標(biāo)識(shí),這里我們只要?jiǎng)?chuàng)建userid 是長(zhǎng)度小于32的字符串即可,說(shuō)明書(shū)已經(jīng)看完啦,來(lái),開(kāi)始著手做準(zhǔn)備工作!

??

那我們回到主頁(yè),注冊(cè)登錄

??

然后在機(jī)器人管理界面,創(chuàng)建圖靈機(jī)器人,最多可以創(chuàng)建5個(gè),由此得出對(duì)應(yīng)的5個(gè)apikey。(實(shí)際上一個(gè)就夠啦)

apikey是針對(duì)接口訪問(wèn)的授權(quán)方式。

??

準(zhǔn)備工作做完啦,接下來(lái)想想該如何寫(xiě)代碼

第二步:創(chuàng)建自己的聊天機(jī)器人

請(qǐng)求過(guò)程:首先創(chuàng)建post請(qǐng)求所需的json數(shù)據(jù),然后向指定的接口發(fā)起post請(qǐng)求即可,

而且從參數(shù)說(shuō)明中可以看到,只有參數(shù) perception 和 userinfo 才是必須的

想不清楚的可以看提示哦~

【提示】

userid = str(1)

1 可以替換成任何長(zhǎng)度小于32的字符串哦 ~

apikey = str(‘A')

這里的A,記得替換成你自己的apikey哦~

對(duì)咯,還有件小事需要注意一下,有時(shí)候可能你的代碼沒(méi)有錯(cuò),但最后顯示加密錯(cuò)誤,那是apikey過(guò)期了,不過(guò)沒(méi)關(guān)系,不是可以最多創(chuàng)建5個(gè)機(jī)器人嘛,換一個(gè)apikey試試就好咯~

【解答】

選擇語(yǔ)言
import requests
import json

userid = str(1)
# 1 可以替換成任何長(zhǎng)度小于32的字符串哦 
apikey = str(''A)
# 這里的A,記得替換成你自己的apikey哦~
# 創(chuàng)建post函數(shù)
def robot(content):
    # 圖靈api
    api = r'http://openapi./openapi/api/v2'
    # 創(chuàng)建post提交的數(shù)據(jù)
    data = {
        'perception': {
            'inputText': {
                'text': content
                         }
                      },
        'userInfo': {
                    'apiKey': apikey,
                    'userId': userid,
                    }
    }
    # 轉(zhuǎn)化為json格式
    jsondata = json.dumps(data)
    # 發(fā)起post請(qǐng)求
    response = requests.post(api, data = jsondata)
    # 將返回的json數(shù)據(jù)解碼
    robot_res = json.loads(response.content)
    # 提取對(duì)話數(shù)據(jù)
    print(robot_res['results'][0]['values']['text'])

for x in range(10):
    content = input('talk:')
    # 輸入對(duì)話內(nèi)容 
    robot(content)
    if x == 10:
        break 
        # 十次之后就結(jié)束對(duì)話,數(shù)字可以改哦,你想幾次就幾次
#當(dāng)然咯,你也可以加一些stopwords,只要說(shuō)了這些詞就可以終止聊天

while True:
    content = input('talk:')
    # 輸入對(duì)話內(nèi)容 
    robot(content)
    if content == 'bye':
    # 設(shè)置stopwords
        break

#但是,我覺(jué)得吧,喜歡和聊天機(jī)器人玩的都是話癆,所以,可以最后加個(gè)死循環(huán),如下:

# 創(chuàng)建對(duì)話死循環(huán)
while True:
    # 輸入對(duì)話內(nèi)容
    content = input('talk:')
    robot(content)

這個(gè)練習(xí)可能會(huì)遇到的問(wèn)題

1、api = r'http://openapi./openapi/api/v2'  為什么要寫(xiě)成這種格式,而不是常規(guī)的網(wǎng)頁(yè)?為啥有個(gè)r?

加r表示絕對(duì)字符串,這樣里面的\就不會(huì)表達(dá)出其他的意思。r是保持字符串原始值的意思,就是說(shuō)不對(duì)其中的符號(hào)進(jìn)行轉(zhuǎn)義。因?yàn)閣indows下的目錄字符串中通常有斜杠'\',而斜杠在Python的字符串中有轉(zhuǎn)義的作用。例如:\n表示換行如果路徑中有\(zhòng)new就會(huì)被轉(zhuǎn)義。加上r就是為了避免這種情況~

2、對(duì)話限制問(wèn)題

目前圖靈機(jī)器人免費(fèi)用戶對(duì)話限制由原先的100次限制剩3次!

練習(xí)-nlpir人工智能-參考

目前網(wǎng)站無(wú)法訪問(wèn),這個(gè)練習(xí)不用做了哈~

第9關(guān)

練習(xí)-博客達(dá)人-參考

你需要做的事情是:

首先,登錄博客[人人都是蜘蛛俠](https://wordpress-edu-3autumn.localprod./wp-login.php)。

然后,在文章《未來(lái)已來(lái)(三)——同九義何汝秀》中,發(fā)表一個(gè)評(píng)論,這個(gè)評(píng)論中必須要帶有“selenium”這個(gè)詞。

博客登錄頁(yè)面:https://wordpress-edu-3autumn.localprod./wp-login.php

答這道題的時(shí)候,使用可視模式會(huì)對(duì)運(yùn)行結(jié)果有更直觀的了解,如果你想看到瀏覽器的操作過(guò)程,建議你在本地寫(xiě)好練習(xí)答案,然后再?gòu)?fù)制到這里。

【提示】

使用`selenium`操作瀏覽器的方法,就和人一步一步操作的步驟是一樣的:

1. 獲取網(wǎng)頁(yè)

2. 輸入用戶名與密碼,點(diǎn)擊登錄

3. 點(diǎn)擊《未來(lái)已來(lái)(三)——同九義何汝秀》文章標(biāo)題,進(jìn)入文章頁(yè)面

4. 找到評(píng)論區(qū),輸入評(píng)論,點(diǎn)擊發(fā)表評(píng)論

用到的知識(shí)點(diǎn)都是`selenium`提取數(shù)據(jù)的方法,以及操作元素的方法。

【解答】

特別提示:

從博客首頁(yè)進(jìn)入文章頁(yè)面時(shí),需要用到 find_element_by_partial_link_text 通過(guò)鏈接的部分文本獲取超鏈接。

發(fā)表評(píng)論之后,不會(huì)再終端返回運(yùn)行結(jié)果,記得去博客文章的頁(yè)面去看看自己的評(píng)論有沒(méi)有成功~

由于教學(xué)系統(tǒng)中與你本地的瀏覽器設(shè)置方法不同,我給你提供了兩份答案,一份可以在課程系統(tǒng)中運(yùn)行,一份可以在你的本地運(yùn)行。

選擇語(yǔ)言
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.webdriver import RemoteWebDriver

# 獲取用戶輸入的評(píng)論內(nèi)容
while True:
    comment_content = input('請(qǐng)輸入你想要的評(píng)論的內(nèi)容,按回車提交:')
    if comment_content == '':
        print('&' * 5, '評(píng)論內(nèi)容不允許為空', '&' * 5)
    else:
        break


'''方法一:使用自己電腦上的瀏覽器'''
driver = webdriver.Chrome()  # 實(shí)例化瀏覽器對(duì)象
driver.get('https://wordpress-edu-3autumn.localprod./wp-login.php')  # 訪問(wèn)頁(yè)面
time.sleep(2)


'''方法二:使用教學(xué)系統(tǒng)的瀏覽器設(shè)置,只能在網(wǎng)頁(yè)的在線編輯器上運(yùn)行'''
# chrome_options = Options()  # 實(shí)例化Option對(duì)象
# chrome_options.add_argument('--headless')  # 對(duì)瀏覽器的設(shè)置
# driver = webdriver.Chrome('http://thon-class-fos.svc:4444/wd/hub',
#                          chrome_options.to_capabilities())  # 聲明瀏覽器對(duì)象
# driver.get('https://wordpress-edu-3autumn.localprod./wp-login.php')  # 訪問(wèn)頁(yè)面


# 定位到用戶名輸入框,輸入用戶名
login_name = driver.find_element_by_id('user_login')
login_name.send_keys('spiderman')
time.sleep(1)
# 定位到密碼輸入框,輸入密碼
password = driver.find_element_by_id('user_pass')
password.send_keys('crawler334566')
# 定位到登錄按鈕,并點(diǎn)擊按鈕
submit_btn = driver.find_element_by_id('wp-submit')
submit_btn.click()
time.sleep(2)


# 通過(guò)鏈接的部分文本定位到'《未來(lái)已來(lái)(三)——同九義何汝秀》'這篇文章
# 獲取到該文章對(duì)應(yīng)的a標(biāo)簽(超鏈接),并點(diǎn)擊鏈接進(jìn)入文章詳情頁(yè)
article_link = driver.find_element_by_partial_link_text('同九義何汝秀')
article_link.click()


# 進(jìn)入文章詳情頁(yè),定位到該頁(yè)面下編寫(xiě)評(píng)論的文本框,輸入內(nèi)容
comment_area = driver.find_element_by_id('comment')
comment_area.send_keys(comment_content)
time.sleep(2)
# 定位到提交按鈕,點(diǎn)擊該按鈕提交評(píng)論
comment_submit = driver.find_element_by_id('submit')
comment_submit.click()


# 評(píng)論成功10秒后關(guān)閉瀏覽器
time.sleep(10)
driver.close()
print('#' * 6, '評(píng)論成功,瀏覽器已關(guān)閉', '#' * 6)

練習(xí)-Python之禪-參考

題目要求

獲取網(wǎng)站[你好,蜘蛛俠!](https://localprod.m/python-manuscript/hello-spiderman/)的Python之禪中文英對(duì)照文本。

需要通過(guò)兩種方法獲取:

- 只使用`selenium`

- `selenium`與`BeautifulSoup`配合

【講解】

[你好,蜘蛛俠!](https://localprod.m/python-manuscript/hello-spiderman/)是一個(gè)動(dòng)態(tài)網(wǎng)頁(yè),URL:https://localprod.m/python-manuscript/hello-spiderman/

Python之禪的內(nèi)容沒(méi)有存在網(wǎng)頁(yè)源代碼中,無(wú)法通過(guò)`requests.get()`與`BeautifulSoup`提取“Python之禪”的內(nèi)容,不過(guò),我們可以通過(guò)`selenium`獲取到。

方法如下:

0. 使用`selenium`獲取網(wǎng)頁(yè)

1. 輸入你喜歡的老師和助教,點(diǎn)擊提交

2. 提取`Elements`中渲染完成的完整網(wǎng)頁(yè)源代碼中的,中英文對(duì)照的Python之禪

我在課堂講解中帶你做過(guò)前兩步了,第三步正是你現(xiàn)在需要做的。

我們可以用兩種方式完成它~

第一種方法:

只使用`selenium`。

第二種方法:

使用`selenium`配合`BeautifulSoup`。

第一種方法:selenium

這次我們要用`selenium`單獨(dú)完成這個(gè)爬蟲(chóng)。獲取數(shù)據(jù)、解析數(shù)據(jù)、提取數(shù)據(jù)這三個(gè)步驟全部都由`selenium`來(lái)完成,寫(xiě)代碼吧~

【提示】

前面的步驟,在關(guān)卡課程中都已經(jīng)講過(guò),現(xiàn)在要做的是,在它的基礎(chǔ)之上,獲取中英文的“Python之禪”內(nèi)容。

中文和英文版的“Python之禪”都在同樣的標(biāo)簽中。所以,需要先獲取所有的`class_='content'`標(biāo)簽,然后再?gòu)闹蟹謩e提取標(biāo)題與正文。

具體的方法都寫(xiě)在了代碼注釋中。

由于教學(xué)系統(tǒng)中與你本地的瀏覽器設(shè)置方法不同,我給你提供了兩份答案,一份可以在課程系統(tǒng)中運(yùn)行,一份可以在你的本地運(yùn)行。

【解答】

選擇語(yǔ)言
# 下面是只能在爬蟲(chóng)課系統(tǒng)中運(yùn)行的答案:
from selenium.webdriver.chrome.webdriver import RemoteWebDriver # 從selenium庫(kù)中調(diào)用RemoteWebDriver模塊
from selenium.webdriver.chrome.options import Options  # 從options模塊中調(diào)用Options類
import time

chrome_options = Options() # 實(shí)例化Option對(duì)象
chrome_options.add_argument('--headless') # 把Chrome設(shè)置為靜默模式
driver = RemoteWebDriver('http://thon-class-fos.svc:4444/wd/hub', chrome_options.to_capabilities()) # 設(shè)置瀏覽器引擎為遠(yuǎn)程瀏覽器

chrome_options = Options() # 實(shí)例化Option對(duì)象
chrome_options.add_argument('--headless') # 把Chrome設(shè)置為靜默模式
driver = RemoteWebDriver('http://thon-class-fos.svc:4444/wd/hub', chrome_options.to_capabilities()) # 設(shè)置瀏覽器引擎為遠(yuǎn)程瀏覽器

driver.get('https://localprod.m/python-manuscript/hello-spiderman/') # 訪問(wèn)頁(yè)面
time.sleep(2) # 暫停兩秒,等待瀏覽器緩沖

teacher = driver.find_element_by_id('teacher') # 找到【請(qǐng)輸入你喜歡的老師】下面的輸入框位置
teacher.send_keys('必須是吳楓呀') # 輸入文字
assistant = driver.find_element_by_name('assistant') # 找到【請(qǐng)輸入你喜歡的助教】下面的輸入框位置
assistant.send_keys('都喜歡') # 輸入文字
button = driver.find_element_by_class_name('sub') # 找到【提交】按鈕
button.click() # 點(diǎn)擊【提交】按鈕
time.sleep(1)

contents = driver.find_elements_by_class_name('content') # 定位到Python之禪所在的標(biāo)簽
for content in contents:
    title = content.find_element_by_tag_name('h1').text # 提取標(biāo)題
    chan = content.find_element_by_tag_name('p').text # 提取正文
    print(title + '\n' + chan + '\n') # 打印標(biāo)題與正文
driver.close()
選擇語(yǔ)言
# 下面是只能在你的本地運(yùn)行的答案:
from selenium import  webdriver # 從selenium庫(kù)中調(diào)用webdriver模塊
import time

driver = webdriver.Chrome() # 聲明瀏覽器對(duì)象
driver.get('https://localprod.m/python-manuscript/hello-spiderman/') # 訪問(wèn)頁(yè)面
time.sleep(2) # 暫停兩秒,等待瀏覽器緩沖

teacher = driver.find_element_by_id('teacher') # 找到【請(qǐng)輸入你喜歡的老師】下面的輸入框位置
teacher.send_keys('必須是吳楓呀') # 輸入文字
assistant = driver.find_element_by_name('assistant') # 找到【請(qǐng)輸入你喜歡的助教】下面的輸入框位置
assistant.send_keys('都喜歡') # 輸入文字
button = driver.find_element_by_class_name('sub') # 找到【提交】按鈕
button.click() # 點(diǎn)擊【提交】按鈕
time.sleep(1)

contents = driver.find_elements_by_class_name('content') # 定位到Python之禪所在的標(biāo)簽
for content in contents:
    title = content.find_element_by_tag_name('h1').text # 提取標(biāo)題
    chan = content.find_element_by_tag_name('p').text # 提取正文
    print(title + '\n' + chan + '\n') # 打印標(biāo)題與正文
driver.close()

第二種方法:selenium 與 BeautifulSoup配合

先用`selenium`獲取到渲染完成的`Elements`中的網(wǎng)頁(yè)源代碼,然后,`BeautifulSoup`登場(chǎng)解析和提取數(shù)據(jù)。

【提示】

爬取到的文字中,前面會(huì)有一些空格,可以使用`replace(' ','')`去掉文字前面的空格。

這是字符串對(duì)象的一個(gè)方法,它的意思是,把第一個(gè)參數(shù)的字符串用第二個(gè)參數(shù)的字符串替代。

【解答】

具體的方法都寫(xiě)在了代碼注釋中。

由于教學(xué)系統(tǒng)中與你本地的瀏覽器設(shè)置方法不同,我給你提供了兩份答案,一份可以在課程系統(tǒng)中運(yùn)行,一份可以在你的本地運(yùn)行。

選擇語(yǔ)言
# 下面是只能在爬蟲(chóng)課系統(tǒng)中運(yùn)行的答案:
from selenium.webdriver.chrome.webdriver import RemoteWebDriver # 從selenium庫(kù)中調(diào)用RemoteWebDriver模塊
from selenium.webdriver.chrome.options import Options # 從options模塊中調(diào)用Options類
from bs4 import BeautifulSoup
import time

chrome_options = Options() # 實(shí)例化Option對(duì)象
chrome_options.add_argument('--headless') # 把Chrome設(shè)置為靜默模式
driver = RemoteWebDriver('http://thon-class-fos.svc:4444/wd/hub', chrome_options.to_capabilities()) # 設(shè)置瀏覽器引擎為遠(yuǎn)程瀏覽器

driver.get('https://localprod.m/python-manuscript/hello-spiderman/') # 訪問(wèn)頁(yè)面
time.sleep(2) # 暫停兩秒,等待瀏覽器緩沖

teacher = driver.find_element_by_id('teacher') # 定位到【請(qǐng)輸入你喜歡的老師】下面的輸入框位置
teacher.send_keys('必須是吳楓呀') # 輸入文字
assistant = driver.find_element_by_name('assistant') # 定位到【請(qǐng)輸入你喜歡的助教】下面的輸入框位置
assistant.send_keys('都喜歡') # 輸入文字
button = driver.find_element_by_class_name('sub') # 定位到【提交】按鈕
button.click() # 點(diǎn)擊【提交】按鈕
time.sleep(1) # 等待一秒

pageSource = driver.page_source # 獲取頁(yè)面信息
soup = BeautifulSoup(pageSource,'html.parser')  # 使用bs解析網(wǎng)頁(yè)
contents = soup.find_all(class_='content') # 找到源代碼Python之禪中文版和英文版所在的元素
for content in contents:  # 遍歷列表
    title = content.find('h1').text # 提取標(biāo)題
    chan = content.find('p').text.replace('  ','') # 提取Python之禪的正文,并且去掉文字前面的所有空格
    print(title + chan + '\n') # 打印Python之禪的標(biāo)題與正文
driver.close()


# 下面是只能在你的本地運(yùn)行的答案:
from selenium import  webdriver # 從selenium庫(kù)總調(diào)用webdriver模塊
import time
from bs4 import BeautifulSoup

driver = webdriver.Chrome() # 聲明瀏覽器對(duì)象
driver.get('https://localprod.m/python-manuscript/hello-spiderman/') # 訪問(wèn)頁(yè)面
time.sleep(2) # 暫停兩秒,等待瀏覽器緩沖

teacher = driver.find_element_by_id('teacher') # 定位到【請(qǐng)輸入你喜歡的老師】下面的輸入框位置
teacher.send_keys('必須是吳楓呀') # 輸入文字
assistant = driver.find_element_by_name('assistant') # 定位到【請(qǐng)輸入你喜歡的助教】下面的輸入框位置
assistant.send_keys('都喜歡') # 輸入文字
button = driver.find_element_by_class_name('sub') # 定位到【提交】按鈕
button.click() # 點(diǎn)擊【提交】按鈕
time.sleep(1) # 等待一秒

pageSource = driver.page_source # 獲取頁(yè)面信息
soup = BeautifulSoup(pageSource,'html.parser')  # 使用bs解析網(wǎng)頁(yè)
contents = soup.find_all(class_='content') # 找到源代碼Python之禪中文版和英文版所在的元素
for content in contents:  # 遍歷列表
    title = content.find('h1').text # 提取標(biāo)題
    chan = content.find('p').text.replace('  ','') # 提取Python之禪的正文,并且去掉文字前面的所有空格
    print(title + chan + '\n') # 打印Python之禪的標(biāo)題與正文
driver.close()

第10關(guān)

練習(xí)-周末吃什么-參考

第一步:明確目標(biāo)

先明確目標(biāo):我們?cè)诘?關(guān)爬取了下廚房網(wǎng)站中的“本周最受歡迎菜譜”,現(xiàn)在,我們完善這個(gè)程序,讓程序在每個(gè)周五爬取數(shù)據(jù),并把菜譜發(fā)送到我們的郵箱。

【講解】

先明確目標(biāo):我們?cè)诘?關(guān)爬取了下廚房網(wǎng)站中的“本周最受歡迎菜譜”,現(xiàn)在,我們完善這個(gè)程序,讓程序在每個(gè)周五爬取數(shù)據(jù),并把菜譜發(fā)送到我們的郵箱。

該項(xiàng)目和第10關(guān)課堂的項(xiàng)目是非常相似的。

第二步:分析過(guò)程

再分析過(guò)程:這個(gè)程序一共分為三部分:爬蟲(chóng)、通知和定時(shí)。

【講解】

這個(gè)程序一共分為三部分,知識(shí)我們都掌握了。

0.爬蟲(chóng):爬取下廚房網(wǎng)站中本周最歡迎菜譜的菜名、鏈接、原材料。

1.通知:用smtplib、email庫(kù)來(lái)發(fā)送郵件。

2.定時(shí):用schedule和time庫(kù)定時(shí)執(zhí)行程序。

我們分別寫(xiě)出來(lái),然后封裝成函數(shù)。

先把每個(gè)程序?qū)懗鰜?lái),然后拼裝到一起;鑒于爬蟲(chóng)程序已經(jīng)學(xué)過(guò),就直接把代碼提供給大家。

第三步:代碼實(shí)現(xiàn)

接下來(lái)就是寫(xiě)代碼啦。

0.爬蟲(chóng):爬蟲(chóng)代碼已經(jīng)在課堂上學(xué)過(guò),所以直接把爬蟲(chóng)代碼提供給大家,并請(qǐng)大家先封裝爬蟲(chóng)代碼:

選擇語(yǔ)言
import requests
from bs4 import BeautifulSoup

res_foods = requests.get('http://www.xiachufang.com/explore/')
bs_foods = BeautifulSoup(res_foods.text,'html.parser')
list_foods = bs_foods.find_all('div',class_='info pure-u')

list_all = []

for food in list_foods:
    tag_a = food.find('a')
    name = tag_a.text[17:-13]
    URL = 'http://www.xiachufang.com'+tag_a['href']
    tag_p = food.find('p',class_='ing ellipsis')
    ingredients = tag_p.text[1:-1]
    list_all.append([name,URL,ingredients])
print(list_all)

1.郵件:郵件代碼是第10關(guān)所學(xué)的內(nèi)容,下面提供代碼給大家,但最好是回憶不起來(lái)再看;寫(xiě)完代碼后請(qǐng)大家封裝代碼。

(仍然提醒同學(xué)們,學(xué)習(xí)系統(tǒng)會(huì)記錄大家輸入的內(nèi)容??紤]到信息隱私的問(wèn)題,大家不要在這里輸入自己的郵箱密碼或賬號(hào)。因此,請(qǐng)你在本地運(yùn)行郵件相關(guān)的代碼)

選擇語(yǔ)言
import smtplib 
from email.mime.text import MIMEText
from email.header import Header
#引入smtplib、MIMETex和Header

mailhost='smtp.qq.com'
#把qq郵箱的服務(wù)器地址賦值到變量mailhost上,地址應(yīng)為字符串格式
qqmail = smtplib.SMTP()
#實(shí)例化一個(gè)smtplib模塊里的SMTP類的對(duì)象,這樣就可以調(diào)用SMTP對(duì)象的方法和屬性了
qqmail.connect(mailhost,25)
#連接服務(wù)器,第一個(gè)參數(shù)是服務(wù)器地址,第二個(gè)參數(shù)是SMTP端口號(hào)。
#以上,皆為連接服務(wù)器。

account = input('請(qǐng)輸入你的郵箱:')
#獲取郵箱賬號(hào),為字符串格式
password = input('請(qǐng)輸入你的密碼:')
#獲取郵箱密碼,為字符串格式
qqmail.login(account,password)
#登錄郵箱,第一個(gè)參數(shù)為郵箱賬號(hào),第二個(gè)參數(shù)為郵箱密碼
#以上,皆為登錄郵箱。

receiver=input('請(qǐng)輸入收件人的郵箱:')
#獲取收件人的郵箱。

content=input('請(qǐng)輸入郵件正文:')
#輸入你的郵件正文,為字符串格式
message = MIMEText(content, 'plain', 'utf-8')
#實(shí)例化一個(gè)MIMEText郵件對(duì)象,該對(duì)象需要寫(xiě)進(jìn)三個(gè)參數(shù),分別是郵件正文,文本格式和編碼
subject = input('請(qǐng)輸入你的郵件主題:')
#輸入你的郵件主題,為字符串格式
message['Subject'] = Header(subject, 'utf-8')
#在等號(hào)的右邊是實(shí)例化了一個(gè)Header郵件頭對(duì)象,該對(duì)象需要寫(xiě)入兩個(gè)參數(shù),分別是郵件主題和編碼,然后賦值給等號(hào)左邊的變量message['Subject']。
#以上,為填寫(xiě)主題和正文。

try:
    qqmail.sendmail(account, receiver, message.as_string())
    print ('郵件發(fā)送成功')
except:
    print ('郵件發(fā)送失敗')
qqmail.quit()
#以上為發(fā)送郵件和退出郵箱

2.定時(shí):定時(shí)功能是第10關(guān)教的內(nèi)容,代碼如下,下面提供代碼給大家,但最好回憶不起來(lái)再看;寫(xiě)完代碼后請(qǐng)大家封裝代碼。

選擇語(yǔ)言
import schedule
import time
#引入schedule和time
def job():
    print('I'm working...')
#定義一個(gè)叫job的函數(shù),函數(shù)的功能是打印'I'm working...'
schedule.every(10).minutes.do(job)       #部署每10分鐘執(zhí)行一次job()函數(shù)的任務(wù)
schedule.every().hour.do(job)            #部署每×小時(shí)執(zhí)行一次job()函數(shù)的任務(wù)
schedule.every().day.at('10:30').do(job) #部署在每天的10:30執(zhí)行job()函數(shù)的任務(wù)
schedule.every().monday.do(job)          #部署每個(gè)星期一執(zhí)行job()函數(shù)的任務(wù)
schedule.every().wednesday.at('13:15').do(job)#部署每周三的13:15執(zhí)行函數(shù)的任務(wù)
while True:
    schedule.run_pending()
    time.sleep(1) 

【解答】

老師提供的參考答案是這樣的:

選擇語(yǔ)言
import requests
import smtplib
import schedule
import time
from bs4 import BeautifulSoup
from email.mime.text import MIMEText
from email.header import Header

account = input('請(qǐng)輸入你的郵箱:')
password = input('請(qǐng)輸入你的密碼:')
receiver = input('請(qǐng)輸入收件人的郵箱:')

def recipe_spider():
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
    res_foods = requests.get('http://www.xiachufang.com/explore/',headers=headers)
    bs_foods = BeautifulSoup(res_foods.text,'html.parser')
    list_foods = bs_foods.find_all('div',class_='info pure-u')
    list_all = ''
    num=0
    for food in list_foods:
        num=num+1
        tag_a = food.find('a')
        name = tag_a.text.strip()
        url = 'http://www.xiachufang.com'+tag_a['href']
        tag_p = food.find('p',class_='ing ellipsis')
        ingredients = tag_p.text.strip()
        food_info = '''
        序號(hào): %s
        菜名: %s
        鏈接: %s
        原料: %s
        '''%(num,name,url,ingredients)
        list_all=list_all+food_info
    return(list_all)

def send_email(list_all):
    global account,password,receiver
    mailhost='smtp.qq.com'
    qqmail = smtplib.SMTP()
    qqmail.connect(mailhost,25)
    qqmail.login(account,password)
    content= '親愛(ài)的,本周的熱門菜譜如下'+list_all
    message = MIMEText(content, 'plain', 'utf-8')
    subject = '周末吃個(gè)啥'
    message['Subject'] = Header(subject, 'utf-8')
    try:
        qqmail.sendmail(account, receiver, message.as_string())
        print ('郵件發(fā)送成功')
    except:
        print ('郵件發(fā)送失敗')
    qqmail.quit()

def job():
    print('開(kāi)始一次任務(wù)')
    list_all = recipe_spider()
    send_email(list_all)
    print('任務(wù)完成')

schedule.every().friday.at('18:00').do(job)#部署每周三的13:15執(zhí)行函數(shù)的任務(wù)
while True:
    schedule.run_pending()
    time.sleep(1) 

練習(xí)-看個(gè)電影吧-參考

第一步:明確目標(biāo)

先明確目標(biāo):每個(gè)周五,程序在豆瓣TOP250榜單中隨機(jī)選取三部電影,然后去爬取三部電影的下載鏈接,并把鏈接發(fā)送到我們的郵箱。

【講解】

先明確目標(biāo):每個(gè)周五,程序在豆瓣TOP250榜單中隨機(jī)選取三部電影,然后去爬取三部電影的下載鏈接,并把鏈接發(fā)送到我們的郵箱。該項(xiàng)目和第10關(guān)課堂的是非常相似的。

第二步:分析過(guò)程

我們來(lái)看看這個(gè)項(xiàng)目的實(shí)現(xiàn)思路。

【講解】

這個(gè)程序一共分為四部分:

??

0.電影榜單爬蟲(chóng):爬取豆瓣電影Top250的榜單,并存儲(chǔ)文件到本地。

1.電影鏈接爬蟲(chóng):每周五讀取榜單中的三部電影,然后去爬取電影的下載鏈接。

2.通知功能:再把爬到的鏈接以郵件的形式發(fā)送給自己。

3.定時(shí)功能:用schedule和time庫(kù)定時(shí)執(zhí)行程序。

可以把4段代碼分別寫(xiě)出來(lái),然后封裝成函數(shù)。鑒于爬蟲(chóng)程序已經(jīng)做過(guò)練習(xí),會(huì)直接把代碼提供給大家。

電影榜單的爬蟲(chóng)是第3關(guān)課后的必做練習(xí),電影鏈接的爬蟲(chóng)是第3關(guān)的選做練習(xí),所以該練習(xí)的重點(diǎn)不會(huì)放在爬蟲(chóng)上。

第三步:代碼實(shí)現(xiàn)(上)

【代碼實(shí)現(xiàn)】又分為上中下。上、中分別把四段代碼寫(xiě)出來(lái),下是封裝組裝代碼。

上:每周五晚上去豆瓣電影Top250的榜單上隨機(jī)抽取3部,然后去下載這3部電影的鏈接,并打印出來(lái)。

先把兩段爬蟲(chóng)的代碼提供給大家,請(qǐng)大家先閱讀,然后去寫(xiě)代碼。(當(dāng)然,你用你自己寫(xiě)的代碼也是一樣的,只要最后實(shí)現(xiàn)的功能和題目一致)

選擇語(yǔ)言
#這是爬取豆瓣電影Top250,并存為本地csv的代碼
import requests,  random, csv
from bs4 import BeautifulSoup
csv_file=open('movieTop.csv', 'w', newline='',encoding='utf-8')
writer = csv.writer(csv_file)

for x in range(10):
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
    url = 'https://movie.douban.com/top250?start=' + str(x*25) + '&filter='
    res = requests.get(url,headers=headers)
    bs = BeautifulSoup(res.text, 'html.parser')
    bs = bs.find('ol', class_='grid_view')
    for titles in bs.find_all('li'):
        title = titles.find('span', class_='title').text
        list1 = [title]
        writer.writerow(list1)
csv_file.close()

選擇語(yǔ)言
# 這是爬電影的下載鏈接的代碼
import requests
from bs4 import BeautifulSoup
from urllib.request import quote

movie=input('你想看什么電影?')
gbkmovie = movie.encode('gbk')
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
urlsearch = 'http://s./plus/so.php?typeid=1&keyword='+quote(gbkmovie)
res = requests.get(urlsearch,headers=headers)
res.encoding='gbk'
soup_movie = BeautifulSoup(res.text,'html.parser')
urlpart=soup_movie.find(class_='co_content8').find_all('table')
if urlpart:
    urlpart=urlpart[0].find('a')['href']
    urlmovie='https://www./'+urlpart
    res1=requests.get(urlmovie)
    res1.encoding='gbk'
    soup_movie1=BeautifulSoup(res1.text,'html.parser')
    urldownload=soup_movie1.find('div',id='Zoom').find('span').find('table').find('a')['href']
    print(urldownload)
else:
    print('沒(méi)有'+movie+'的鏈接')

好,現(xiàn)在,我們需要先讀取存儲(chǔ)到本地的電影榜單的csv文件,然后用random庫(kù)來(lái)隨機(jī)抽取三部電影,再去下載相應(yīng)的電影鏈接,并把電影鏈接打印出來(lái)。

請(qǐng)開(kāi)始寫(xiě)代碼吧。

【提示】

如果對(duì)這里的爬蟲(chóng)代碼有疑惑,建議先完成第3關(guān)的練習(xí)和第6關(guān)的練習(xí)。

【解答】

選擇語(yǔ)言
import requests,csv,random
from bs4 import BeautifulSoup
from urllib.request import quote
# 以上,為引入相應(yīng)的庫(kù)。

csv_file=open('movieTop.csv', 'w', newline='',encoding='utf-8')
writer = csv.writer(csv_file)
for x in range(10):
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
    url = 'https://movie.douban.com/top250?start=' + str(x*25) + '&filter='
    res = requests.get(url,headers=headers)
    bs = BeautifulSoup(res.text, 'html.parser')
    bs = bs.find('ol', class_='grid_view')
    for titles in bs.find_all('li'):
        title = titles.find('span', class_='title').text
        list1 = [title]
        writer.writerow(list1)
csv_file.close()
# 以上,為爬取豆瓣電影Top250的榜單,并存儲(chǔ)為本地的csv文件。

movielist=[]
csv_file=open('movieTop.csv','r',newline='',encoding='utf-8')
reader=csv.reader(csv_file)
for row in reader:
    movielist.append(row[0])
# 以上,為讀取豆瓣電影Top250榜單的csv文件,并寫(xiě)入列表movielist中。
three_movies=random.sample(movielist,3)
# 以上,是從列表movielist中,隨機(jī)抽取三部電影,取出來(lái)的是一個(gè)列表。
for movie in three_movies:
    # 以上,是把電影名從列表中取出來(lái),并把其數(shù)據(jù)類型變?yōu)樽址O旅骈_(kāi)始,就是你熟悉的下載電影鏈接的代碼了。
    gbkmovie = movie.encode('gbk')
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
    urlsearch = 'http://s./plus/so.php?typeid=1&keyword='+quote(gbkmovie)
    res = requests.get(urlsearch,herders=headers)
    res.encoding='gbk'
    soup_movie = BeautifulSoup(res.text,'html.parser')
    urlpart=soup_movie.find(class_='co_content8').find_all('table')
    if urlpart:
        urlpart=urlpart[0].find('a')['href']
        urlmovie='https://www./'+urlpart
        res1=requests.get(urlmovie)
        res1.encoding='gbk'
        soup_movie1=BeautifulSoup(res1.text,'html.parser')
        urldownload=soup_movie1.find('div',id='Zoom').find('span').find('table').find('a')['href']
        content=movie+'\n'+urldownload
        print(content)
    else:
        content='沒(méi)有'+movie+'的下載鏈接'
        print(content)

第四步:代碼實(shí)現(xiàn)(中)

接下來(lái),我們來(lái)完成發(fā)送郵件,以及定時(shí)功能的代碼,然后在下一步我們?cè)俜庋b、組合四段代碼。

郵件代碼是第10關(guān)所學(xué)的內(nèi)容,下面提供代碼給大家。

(仍然提醒同學(xué)們,學(xué)習(xí)系統(tǒng)會(huì)記錄大家輸入的內(nèi)容??紤]到信息隱私的問(wèn)題,大家不要在這里輸入自己的郵箱密碼或賬號(hào)。因此,請(qǐng)你在本地運(yùn)行郵件相關(guān)的代碼)

選擇語(yǔ)言
import smtplib
from email.mime.text import MIMEText
from email.header import Header
#引入smtplib、MIMETex和Header

mailhost='smtp.qq.com'
#把qq郵箱的服務(wù)器地址賦值到變量mailhost上,地址應(yīng)為字符串格式
qqmail = smtplib.SMTP()
#實(shí)例化一個(gè)smtplib模塊里的SMTP類的對(duì)象,這樣就可以調(diào)用SMTP對(duì)象的方法和屬性了
qqmail.connect(mailhost,25)
#連接服務(wù)器,第一個(gè)參數(shù)是服務(wù)器地址,第二個(gè)參數(shù)是SMTP端口號(hào)。
#以上,皆為連接服務(wù)器。

account = input('請(qǐng)輸入你的郵箱:')
#獲取郵箱賬號(hào),為字符串格式
password = input('請(qǐng)輸入你的密碼:')
#獲取郵箱密碼,為字符串格式
qqmail.login(account,password)
#登錄郵箱,第一個(gè)參數(shù)為郵箱賬號(hào),第二個(gè)參數(shù)為郵箱密碼
#以上,皆為登錄郵箱。

receiver=input('請(qǐng)輸入收件人的郵箱:')
#獲取收件人的郵箱。

#content為上面的電影鏈接
#輸入你的郵件正文,為字符串格式
message = MIMEText(content, 'plain', 'utf-8')
#實(shí)例化一個(gè)MIMEText郵件對(duì)象,該對(duì)象需要寫(xiě)進(jìn)三個(gè)參數(shù),分別是郵件正文,文本格式和編碼
subject = '電影鏈接'
#輸入你的郵件主題,為字符串格式
message['Subject'] = Header(subject, 'utf-8')
#在等號(hào)的右邊是實(shí)例化了一個(gè)Header郵件頭對(duì)象,該對(duì)象需要寫(xiě)入兩個(gè)參數(shù),分別是郵件主題和編碼,然后賦值給等號(hào)左邊的變量message['Subject']。
#以上,為填寫(xiě)主題和正文。

try:
    qqmail.sendmail(account, receiver, message.as_string())
    print ('郵件發(fā)送成功')
except:
    print ('郵件發(fā)送失敗')
qqmail.quit()
#以上為發(fā)送郵件和退出郵箱

#定時(shí)功能是第10關(guān)教的內(nèi)容,代碼如下,下面提供代碼給大家,但最好回憶不起來(lái)再看。
import schedule
import time
#引入schedule和time
def job():
    print('I'm working...')
#定義一個(gè)叫job的函數(shù),函數(shù)的功能是打印'I'm working...'

schedule.every(10).minutes.do(job)    #部署每10分鐘執(zhí)行一次job()函數(shù)的任務(wù)
schedule.every().hour.do(job)          #部署每×小時(shí)執(zhí)行一次job()函數(shù)的任務(wù)
schedule.every().day.at('10:30').do(job)#部署每天的10:30執(zhí)行job()函數(shù)任務(wù)
schedule.every().monday.do(job)        #部署每個(gè)星期一執(zhí)行job()函數(shù)的任務(wù)
schedule.every().wednesday.at('13:15').do(job)
#部署每周三的13:15執(zhí)行函數(shù)的任務(wù)

while True:
    schedule.run_pending()
    time.sleep(1)  

【解答】

老師提供的參考答案是這樣的:

選擇語(yǔ)言
import requests,csv,random,smtplib,schedule,time
from bs4 import BeautifulSoup
from urllib.request import quote
from email.mime.text import MIMEText
from email.header import Header

def get_movielist():
    csv_file=open('movieTop.csv', 'w', newline='',encoding='utf-8')
    writer = csv.writer(csv_file)
    for x in range(10):
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
        url = 'https://movie.douban.com/top250?start=' + str(x*25) + '&filter='
        res = requests.get(url,headers=headers)
        bs = BeautifulSoup(res.text, 'html.parser')
        bs = bs.find('ol', class_='grid_view')
        for titles in bs.find_all('li'):
            title = titles.find('span', class_='title').text
            list1 = [title]
            writer.writerow(list1)
    csv_file.close()

def get_randommovie():
    movielist=[]
    csv_file=open('movieTop.csv','r',newline='',encoding='utf-8')
    reader=csv.reader(csv_file)
    for row in reader:
        movielist.append(row[0])
    three_movies=random.sample(movielist,3)
    contents=''
    for movie in three_movies:
        gbkmovie = movie.encode('gbk')
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
        urlsearch = 'http://s./plus/so.php?typeid=1&keyword='+quote(gbkmovie)
        res = requests.get(urlsearch,headers=headers)
        res.encoding='gbk'
        soup_movie = BeautifulSoup(res.text,'html.parser')
        urlpart=soup_movie.find(class_='co_content8').find_all('table')
        if urlpart:
            urlpart=urlpart[0].find('a')['href']
            urlmovie='https://www./'+urlpart
            res1=requests.get(urlmovie)
            res1.encoding='gbk'
            soup_movie1=BeautifulSoup(res1.text,'html.parser')
            urldownload=soup_movie1.find('div',id='Zoom').find('span').find('table').find('a')['href']
            content=movie+'\n'+urldownload+'\n\n'
            print(content)
            contents=contents+content
        else:
            content='沒(méi)有'+movie+'的下載鏈接'
            print(content)
    return contents

def send_movielink(contents):
    mailhost='smtp.qq.com'
    qqmail = smtplib.SMTP()
    qqmail.connect(mailhost,25)
    account = '×××××××××@qq.com' # 因?yàn)槭亲约喊l(fā)給自己,所以郵箱賬號(hào)、密碼都可以提前設(shè)置好,當(dāng)然,也可以發(fā)給別人啦
    password = '×××××××××××××××' # 因?yàn)槭亲约喊l(fā)給自己,所以郵箱賬號(hào)、密碼都可以提前設(shè)置好,當(dāng)然,也可以發(fā)給別人啦。
    qqmail.login(account,password)
    receiver='×××××××××@qq.com'  # 因?yàn)槭亲约喊l(fā)給自己,所以郵箱賬號(hào)、密碼都可以提前設(shè)置好,當(dāng)然,也可以發(fā)給別人啦。
    message = MIMEText(contents, 'plain', 'utf-8')
    subject = '電影鏈接'
    message['Subject'] = Header(subject, 'utf-8')
    try:
        qqmail.sendmail(account, receiver, message.as_string())
        print ('郵件發(fā)送成功')
    except:
        print ('郵件發(fā)送失敗')
    qqmail.quit()

def job():
    get_movielist()
    contents=get_randommovie()
    send_movielink(contents)

schedule.every().friday.at('18:00').do(job)
while True:
    schedule.run_pending()
    time.sleep(1)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多