爬虫精进6

—————————如有疑问,欢迎交流指正————————

第6关

练习-储存电影信息-参考

第一步:分析问题,明确结果

问题需求就是把豆瓣TOP250里面的 序号/电影名/评分/推荐语/链接 都爬取下来,结果是存储在csv和Excel中

【讲解】

问题需求就是把豆瓣TOP250里面的 序号/电影名/评分/推荐语/链接 都爬取下来,结果是存储在csv和Excel中

这里拓展一下如何取标签🏷️~

https://shimo.im/docs/QWQJYGw8CtcwQwyq/ 《豆瓣250爬虫思路详解》

第二步:书写爬虫代码

回顾下第三关的爬虫代码

【解答】

选择语言
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' + '推荐语:' + tes +'\n' + url_movie)
else:
print(num + '.' + title + '——' + comment + '\n' +'\n' + url_movie)

第三步: 完善代码,用Excel存储信息

要存储在Excel中呢,需要先创建工作表,重命名,再设置表头,把爬取的信息写成列表,然后用append函数多行写入Excel,最后命名保存这个Excel 文件。

请改写下方的爬虫代码,实现使用Excel存储信息。

【解答】

选择语言
import requests, bs4, openpyxl
wb=openpyxl.Workbook()
#创建工作薄
sheet=wb.active
#获取工作薄的活动表
sheet.title='movies'
#工作表重命名
sheet['A1'] ='序号' #加表头,给A1单元格赋值
sheet['B1'] ='电影名' #加表头,给B1单元格赋值
sheet['C1'] ='评分' #加表头,给C1单元格赋值
sheet['D1'] ='推荐语' #加表头,给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写成列表,用append函数多行写入Excel
print(num + '.' + title + '——' + comment + '\n' + '推荐语:' + 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')
#最后保存并命名这个Excel文件

第四步:另辟蹊径,用csv格式存储信息

思考下如何用csv创建写入存储呢?

请修改下方代码,实现使用csv存储信息。

【提示】

选择语言
import requests, bs4, csv
#引用csv模块。
csv_file=open('movieTop250.csv', 'w', newline='')
#调用open()函数打开csv文件,传入参数:文件名“movieTop250.csv”、写入模式“w”、newline=''

【解答】

选择语言
import requests, bs4, csv
#引用csv模块。
csv_file=open('movieTop250.csv', 'w', newline='')
#调用open()函数打开csv文件,传入参数:文件名“movieTop250.csv”、写入模式“w”、newline=''。
writer = csv.writer(csv_file)
# 用csv.writer()函数创建一个writer对象。
writer.writerow(['序号', '电影名', '评分', '推荐语', '链接'])
#调用writer对象的writerow()方法,可以在csv文件里写入title:'序号', '电影名', '评分', '推荐语', '链接'
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写成列表,用append函数多行写入Excel
writer.writerow([num + '.' + title + '——' + comment + '\n' + '推荐语:' + tes +'\n' + url_movie])
else:
writer.writerow([num + '.' + title + '——' + comment + '\n' +'\n' + url_movie])
csv_file.close()

记得出现乱码的问题,可以看这里的解决方法哦~

https://shimo.im/docs/hqTrdqwQhCJGktWV/ 《爬虫第6关常见问题解决方法》

第7关

练习-做个测单词的小工具-参考

第一步:分析需求,明确目标

扇贝网:https://www.shanbay.com/已经有一个测单词量的功能,我们要做的就是把这个功能复制下来,并且做点改良,搞一个网页版没有的功能 ———— 自动生成错词本。

在这一步,请阅读文档的同时打开浏览器的扇贝网,跟着我一步步来。

【提示】

这里是扇贝网的测单词量的界面:





想要复制功能,就先做分析,这个网页是怎样的工作流程。

所以,先体验全程,大概分为如下五个页面:





















先看源代码里是否有我们的单词。倘若有,就用find()/find_all()定位提取需要的数据;

没有的话,就要调用【检查】-【Network】 - 【XHR】 - 找数据。

在Headers里看网址,在Preview里看内容。









如图:category/这一个XHR,用的是Get请求方式,访问了网址https://www.shanbay.com/api/v1/vocabtest/category/,下载了一个字典。

其中“data”里面,藏了十个元素。这十个元素,里面对应的内容,就是我们最开始要选择的“词汇范围”。

十个元素,每个里面都有两个内容。0是什么暂时还不知道,先放着。1是我们词汇范围没错。

比如我们选择高考,那么在第2个元素里就有一个0是“NCEE”,有一个1是“高考”。

我们接着看下一个XHR:





这个图片说明:?category=NCEE 这一个XHR,访问了网址https://www.shanbay.com/api/v1/vocabtest/vocabularies/?category=NCEE

在此,“NCEE”出现了两次:这个XHR的名字里面有“NCEE”,它访问的网址里面也有“NCEE”。

这就揭示了一种对应关系:当我们选择“高考”词库,那么下一个XHR,访问的网址就会是用“NCEE”来结尾。

可以多试几个词库验证下我们的猜测,的确里面的对应关系是一致的。考研和NGEE一组,四级和CET4一组,六级和CET6一组。

第1个XHR,所访问的网址规律就是:'https://www.shanbay.com/api/v1/vocabtest/vocabularies/?category='+'你选择的词库,对应的代码'。





如图,它下载到的是一个字典。字典里,包含了用来测试词汇量的50个单词。

第0,它先给出单词。

第1,它给出四个不同的翻译,每个翻译都有一个对应的pk值和rank值。

第2,它再给出一组pk值和rank值。它们,和正确翻译里面的pk值与rank值一致。

那么,我们就可以理清楚,这个网页的工作逻辑。如下图:





到这里,我们就完成了至关重要的“需求分析”这个步骤。

第二步:分步讲解,书写代码 (。▰‿‿▰。) ❤





【讲解】

下面,我将带你一步步完成代码。

(0). 选择题库。

写这个程序,要用到requests模块。

先用requests下载链接,再用res.json()解析下载内容。

让用户选择想测的词库,输入数字编号,获取题库的代码。

提示:记得给input前面加一个int()来转换数据类型

【解答】

选择语言
import requests
lin=requests.get('https://www.shanbay.com/api/v1/vocabtest/category/')
#先用requests下载链接。
js_link = lin.json()
#解析下载得到的内容。
bianhao = int(input('''请输入你选择的词库编号,按Enter确认
1,GMAT  2,考研  3,高考  4,四级  5,六级
6,英专  7,托福  8,GRE  9,雅思  10,任意
>'''))
#让用户选择自己想测的词库,输入数字编号。int()来转换数据类型
ciku = js_link['data'][bianhao-1][0]
print(ciku)

(1). 根据选择的题库,获取50个单词。

第0步我们已经拿到链接,这步直接用requests去下载,re.json()解析即可。

【解答】

选择语言
test = requests.get('https://www.shanbay.com/api/v1/vocabtest/vocabularies/?category='+ciku)
#下载用于测试的50个单词。
words = test.json()
#对测试的单词进行解析。
print(words)

(2). 让用户选择认识的单词:此处,要分别记录下用户认识哪些,不认识哪些。

已经有了单词数据,提取出来让用户识别,并记录用户认识哪些不认识哪些,至少2个list来记录。

50个单词,记得要用循环。用户手动输入自己的选择,用input() 。我们要识别用户的输入,并基于此决定把这个单词放进哪个list,需要用if语句。

提示:当一个元素特别长的时候,给代码多加一个list。

提示:加个换行,优化用户视角。

新增一个list,用于统计用户认识的单词。

创建一个空的列表,用于记录用户认识的单词。

创建一个空的列表,用于记录用户不认识的单词。

启动一个循环,循环的次数等于单词的数量。

如果用户认识:就把这个单词,追加进列表words_knows。

否则,就把这个单词,追加进列表not_knows。

打印一个统计数据:这么多单词,认识几个,认识的有哪些?

【解答】

选择语言
danci = []
#新增一个list,用于统计用户认识的单词
words_knows = []
not_knows = []
print ('测试现在开始。如果你认识这个单词,请输入Y,否则直接敲Enter:')
n=0
for x in words['data']:
    n=n+1
    print ('\n第'+str(n)+'个:'+x['content'])
    #加一个\n,用于换行。
    answer = input('认识请敲Y,否则敲Enter:')
    if answer == 'Y':
        danci.append(x['content'])
        #把用户认识的单词,追加进danci这个list。
        words_knows.append(x)
    else:
        not_knows.append(x)
print ('\n在上述'+str(len(words['data']))+'个单词当中,有'+str(len(danci))+'个是你觉得自己认识的,它们是:')
print(danci)

(3). 对于用户认识的单词,给选择题让用户做:此处要记录用户做对了哪些,做错了哪些。

这一步是第0步和第2步的组合——涉及到第0步中的选择,也涉及到第2步的数据记录。

提示: 面对冗长的字典列表相互嵌套,可以创建字典。

【解答】

选择语言
print ('现在我们来检测一下,你有没有真正掌握它们:')
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('请选择单词\''+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']} 
    #我们创建一个字典,搭建起A、B、C、D和四个rank值的映射关系。
    if dic[xuanze] == y['rank']:
    #此时dic[xuanze]的内容,其实就是rank值,此时的代码含义已经和之前的版本相同了。
        right_num += 1
    else:
        wrong_words.append(y)

(4). 生成报告:50个单词,不认识多少,认识多少,掌握多少,错了多少。

生成报告主要有三部分:第0,是输出统计数据;第1,是打印错题集;第2,是把错题集保存到本地。

【解答】

选择语言
import requests
link = requests.get('https://www.shanbay.com/api/v1/vocabtest/category/')
#先用requests下载链接。
js_link = link.json()
#解析下载得到的内容。
bianhao = int(input('''请输入你选择的词库编号,按Enter确认
1,GMAT  2,考研  3,高考  4,四级  5,六级
6,英专  7,托福  8,GRE  9,雅思  10,任意
>'''))
#让用户选择自己想测的词库,输入数字编号。int()来转换数据类型
ciku = js_link['data'][bianhao-1][0]
#利用用户输入的数字编号,获取题库的代码。如果以输入“高考”的编号“3”为例,那么ciku的值就是,在字典js_link中查找data的值,data是一个list,查找它的第bianhao-1,也就是第2个元素,得到的依然是一个list,再查找该list的第0个元素。最后得到的就是我们想要的NCEE。
test = requests.get('https://www.shanbay.com/api/v1/vocabtest/vocabularies/?category='+ciku)
#下载用于测试的50个单词。
words = test.json()
#对test进行解析。
danci = []
#新增一个list,用于统计用户认识的单词
words_knows = []
#创建一个空的列表,用于记录用户认识的单词。
not_knows = []
#创建一个空的列表,用于记录用户不认识的单词。
print ('测试现在开始。如果你认识这个单词,请输入Y,否则直接敲Enter:')
n=0
for x in words['data']:
#启动一个循环,循环的次数等于单词的数量。
    n=n+1
    print ('\n第'+str(n)+'个:'+x['content'])
    #加一个\n,用于换行。
    answer = input('认识请敲Y,否则敲Enter:')
    #让用户输入自己是否认识。
    if answer == 'Y':
    #如果用户认识:
        danci.append(x['content'])
        words_knows.append(x)
        #就把这个单词,追加进列表words_knows。
    else:
    #否则
        not_knows.append(x)
        #就把这个单词,追加进列表not_knows。
print ('\n在上述'+str(len(words['data']))+'个单词当中,有'+str(len(danci))+'个是你觉得自己认识的,它们是:')
print(danci)
print ('现在我们来检测一下,你有没有真正掌握它们:')
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('请选择单词\''+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']} 
    #我们创建一个字典,搭建起A、B、C、D和四个rank值的映射关系。
    if dic[xuanze] == y['rank']:
    #此时dic[xuanze]的内容,其实就是rank值,此时的代码含义已经和之前的版本相同了。
        right_num += 1
    else:
        wrong_words.append(y)
print ('现在,到了公布成绩的时刻:')
print ('在'+str(len(words['data']))+'个'+js_link['data'][bianhao-1][1]+'词汇当中,你认识其中'+str(len(danci))+'个,实际掌握'+str(right_num)+'个,错误'+str(len(wrong_words))+'个。')
#这是句蛮复杂的话,对照前面的代码和json文件你才能理解它。一个运行示例是:在50个高考词汇当中,你认识其中30个,实际掌握25个,错误5个。
save = input ('是否打印并保存你的错词集?填入Y或N: ')
#询问用户,是否要打印并保存错题集。
if save == 'Y':
#如果用户说是:
    f = open('错题集.txt', 'a+')
    #在当前目录下,创建一个错题集.txt的文档。        
    print ('你记错的单词有:')
    f.write('你记错的单词有:\n')
    #写入'你记错的单词有:\n'
    m=0
    for z in wrong_words:
    #启动一个循环,循环的次数等于,用户的错词数:
        m=m+1
        print (z['content'])
        #打印每一个错词。
        f.write(str(m+1) +'. '+ z['content']+'\n')
        #写入序号,写入错词。           
    print ('你不认识的单词有:')
    f.write('你没记住的单词有:\n')
    #写入'你没记住的单词有:\n'
    s=0
    for x in not_knows:
    #启动一个循环,循环的次数等于,用户不认识的单词数。
        print (x['content'])
        #打印每一个不认识的单词。
        f.write(str(s+1) +'. '+ x['content']+'\n')
        #写入序号,写入用户不认识的词汇。 
    print ('错词和没记住的词已保存至当前文件目录下,下次见!')
    #告诉用户,文件已经保存好。
    #在网页版终端运行时,文件会被写在课程的服务器上,你看不到,但它的确已经存在。
else:
#如果用户不想保存:
    print('下次见!')
    #输出“下次见!”

三步:参考答案

参考答案

选择语言
import requests
link = requests.get('https://www.shanbay.com/api/v1/vocabtest/category/')
#先用requests下载链接。
js_link = link.json()
#解析下载得到的内容。
bianhao = int(input('''请输入你选择的词库编号,按Enter确认
1,GMAT  2,考研  3,高考  4,四级  5,六级
6,英专  7,托福  8,GRE  9,雅思  10,任意
>'''))
#让用户选择自己想测的词库,输入数字编号。int()来转换数据类型
ciku = js_link['data'][bianhao-1][0]
#利用用户输入的数字编号,获取题库的代码。如果以输入“高考”的编号“3”为例,那么ciku的值就是,在字典js_link中查找data的值,data是一个list,查找它的第bianhao-1,也就是第2个元素,得到的依然是一个list,再查找该list的第0个元素。最后得到的就是我们想要的NCEE。
test = requests.get('https://www.shanbay.com/api/v1/vocabtest/vocabularies/?category='+ciku)
#下载用于测试的50个单词。
words = test.json()
#对test进行解析。
danci = []
#新增一个list,用于统计用户认识的单词
words_knows = []
#创建一个空的列表,用于记录用户认识的单词。
not_knows = []
#创建一个空的列表,用于记录用户不认识的单词。
print ('测试现在开始。如果你认识这个单词,请输入Y,否则直接敲Enter:')
n=0
for x in words['data']:
#启动一个循环,循环的次数等于单词的数量。
    n=n+1
    print ('\n第'+str(n)+'个:'+x['content'])
    #加一个\n,用于换行。
    answer = input('认识请敲Y,否则敲Enter:')
    #让用户输入自己是否认识。
    if answer == 'Y':
    #如果用户认识:
        danci.append(x['content'])
        words_knows.append(x)
        #就把这个单词,追加进列表words_knows。
    else:
    #否则
        not_knows.append(x)
        #就把这个单词,追加进列表not_knows。
print ('\n在上述'+str(len(words['data']))+'个单词当中,有'+str(len(danci))+'个是你觉得自己认识的,它们是:')
print(danci)
print ('现在我们来检测一下,你有没有真正掌握它们:')
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('请选择单词\''+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']} 
    #我们创建一个字典,搭建起A、B、C、D和四个rank值的映射关系。
    if dic[xuanze] == y['rank']:
    #此时dic[xuanze]的内容,其实就是rank值,此时的代码含义已经和之前的版本相同了。
        right_num += 1
    else:
        wrong_words.append(y)
print ('现在,到了公布成绩的时刻:')
print ('在'+str(len(words['data']))+'个'+js_link['data'][bianhao-1][1]+'词汇当中,你认识其中'+str(len(danci))+'个,实际掌握'+str(right_num)+'个,错误'+str(len(wrong_words))+'个。')
#这是句蛮复杂的话,对照前面的代码和json文件你才能理解它。一个运行示例是:在50个高考词汇当中,你认识其中30个,实际掌握25个,错误5个。
save = input ('是否打印并保存你的错词集?填入Y或N: ')
#询问用户,是否要打印并保存错题集。
if save == 'Y':
#如果用户说是:
    f = open('错题集.txt', 'a+')
    #在当前目录下,创建一个错题集.txt的文档。        
    print ('你记错的单词有:')
    f.write('你记错的单词有:\n')
    #写入'你记错的单词有:\n'
    m=0
    for z in wrong_words:
    #启动一个循环,循环的次数等于,用户的错词数:
        m=m+1
        print (z['content'])
        #打印每一个错词。
        f.write(str(m+1) +'. '+ z['content']+'\n')
        #写入序号,写入错词。           
    print ('你不认识的单词有:')
    f.write('你没记住的单词有:\n')
    #写入'你没记住的单词有:\n'
    s=0
    for x in not_knows:
    #启动一个循环,循环的次数等于,用户不认识的单词数。
        print (x['content'])
        #打印每一个不认识的单词。
        f.write(str(s+1) +'. '+ x['content']+'\n')
        #写入序号,写入用户不认识的词汇。 
    print ('错词和没记住的词已保存至当前文件目录下,下次见!')
    #告诉用户,文件已经保存好。
    #在网页版终端运行时,文件会被写在课程的服务器上,你看不到,但它的确已经存在。
else:
#如果用户不想保存:
    print('下次见!')
    #输出“下次见!

第8关

练习-我家附近有啥好吃的-参考

项目目标:在本练习,我们会借助cookies的相关知识,使用Python登录饿了么网站,爬取自己家附近的餐厅列表。

网站地址:https://www.ele.me/home/

【讲解】

在本练习,我们会借助cookies的相关知识,使用Python登录饿了么网站,爬取自己家附近的餐厅。

网站地址:https://www.ele.me/home/

想要顺利地爬取饿了么上面的餐厅列表,我们需要先自己前往饿了么网站,手动找到餐厅列表所在位置。然后,再用Python代码去模拟这个过程。

首先,打开饿了么首页:(https://www.ele.me/home/)

打开【检查】工具,选择【Network】,勾选【Preserve log】(因为等会可能会有页面跳转,勾选上防止在跳转过程中请求被清空)。





然后,输入地址,如:“腾讯大厦”(推荐先把文字打好,再利用复制粘贴一次性输入,不要一个字一个字填输),页面会弹出许多个地址给你选择。此刻,会看到右侧的Network面板里多出一个XHR:pois?……

这说明,这些地址列表和XHR之间存在有对应关系。记住这个XHR,它很重要,后面会用到。

我们先点击一个地址,比如我选择的第0个,“腾讯大厦”,它会跳转至一个新地址:(https://www.ele.me/place/ws100xkkpznf?latitude=22.54055&longitude=113.934401)



击登录,会来到(https://h5.ele.me/login/#redirect=https%3A%2F%2Fwww.ele.me%2Fplace%2Fws100xkkpznf%3Flatitude%3D22.54055%26longitude%3D113.934401)





阅读该URL,很容易能够看出这个是一个登录页,因为有login存在。同时它在?之后所携带的参数,含义是来源:我们刚刚从哪个URL跳转过来。

输入手机号码,点击收取验证码,此时浏览器会发起请求:mobile_send_code。

手机收到验证码,输入验证码,完成登录。页面会重新跳转回我们刚刚来到的地址,此时的页面,出现了我们想要的餐馆名。





login_by_mobile即是登录获取cookies的那个请求。

通过翻找Network,我们定位到,存储有餐厅列表的请求是XHR:restaurants…

该请求需要若干参数,如下:

1. extras[]:activities

2. geohash:通过搜索得之,这是一个能够代表地理位置的字符串。

3. latitude:纬度

4. limit:一次加载多少个餐馆

5. longitude:经度

6. offset:起始值

7. terminal: web

思考实现方案

这个网站,要求登录才能实现爬取餐馆列表。所以我们需要用到cookies来实现。

所以理论上,我们的代码顺序应该是:模拟登录获取cookies,再带着cookies去请求餐馆列表。

不过,必须要指出的是。请求餐馆列表,还需要一些参数才行。这些参数,和我们刚刚在首页输入“腾讯大厦”四个字的操作有关。

具体,我们在做代码实操时再展开讲解。

所以正确的过程应该是:

- 模拟登录获取cookies

- 模拟输入“腾讯大厦”获取必要的参数

- 带着参数和cookies,去请求餐馆列表

其中,前两步可以顺序调换。

【讲解】

下面,我将带你一步步完成代码。

一、使用session和cookies模拟登录

体验登录:https://h5.ele.me/login/

提示:此处需要先模拟发送验证码的请求,再模拟登录的请求。

提示:请求验证码时,会返回一个json,json里会有validate_token。它在我们输入账号验证码模拟登录的时候,会用到。

模拟登录参考示例:

选择语言
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 = ' https://wordpress-edu-3autumn.localprod.forc.work/wp-login.php'
#登录的网址。
data = {'log': input('请输入你的账号:'),
'pwd': input('请输入你的密码:'),
'wp-submit': '登录',
'redirect_to': 'https://wordpress-edu-3autumn.localprod.forc.work/wp-admin/',
'testcookie': '1'}
#登录的参数。
session.post(url, headers=headers, data=data)
#在会话下,用post发起登录请求。

【解答】

选择语言
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.ele.me/restapi/eus/login/mobile_send_code'
# 发送验证码的网址
tel = input('请输入手机号码:')
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.ele.me/restapi/eus/login/login_by_mobile'
code = input('请输入手机验证码:')
data_2 = {'mobile':tel,
'scf':'ms',
'validate_code':code,
'validate_token':token}
session.post(url_2,headers=headers,data=data_2)

二、模拟输入地址,获取必要参数

为了请求餐馆列表,我们需要几个关键参数:

1. geohash:通过搜索得之,这是一个能够代表地理位置的字符串。

2. latitude:纬度

3. longitude:经度

这三个参数,都需要模拟输入地址来获得。请打印出这三个参数。

体验输入地址:https://www.ele.me/home/

提示:本步骤不需要模拟登录

提示:在模拟该请求时需要用到城市的geohash值,可在XHR里查看自己城市的geohash值

【解答】

选择语言
import requests
# 导入requests模块。
address_url = 'https://www.ele.me/restapi/v2/pois?'
# 你能够在【Headers】-【General】里找到这个链接。
place = input('请输入你的收货地址:')
# 使用input输入收获地址,赋值给place。
# 因为我们的geohash使用了深圳的值,所以推荐你测试的时候使用“腾讯大厦”。
params = {'extras[]':'count','geohash':'ws105rz9smwm','keyword':place,'limit':'20','type':'nearby'}
# 将要传递的参数封装成字典,键与值都要用字符串,其中keyword对于的值是place。
address_res = requests.get(address_url,params=params)
# 发起请求,将响应的结果,赋值给address_res
address_json = address_res.json()
# 将响应的结果转为列表/字典。
print('以下,是与'+place+'相关的位置信息:\n')
n=0
# 添加一个计数器,作为序号。
for address in address_json:
# 遍历我们刚爬取的地址列表。
print(str(n)+'. '+address['name']+':'+address['short_address']+'\n')
# 打印序号,地址名,短地址。
n = n+1
# 给计数器加1。
address_num = int(input('请输入您选择位置的序号:'))
# 让用户选择序号。
final_address = address_json[address_num]
# 确认地址。
print(final_address['geohash'])
print(final_address['latitude'])
print(final_address['longitude'])

三、带cookies和参数请求餐馆列表

最后一步,将上述两组代码组合。

拿到cookies和参数,完成请求餐馆列表。

我帮你预置了前两个代码,你可以在此基础上完成本关卡任务。

【解答】

选择语言
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.ele.me/restapi/eus/login/mobile_send_code'
tel = input('请输入手机号码:')
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.ele.me/restapi/eus/login/login_by_mobile'
code = input('请输入手机验证码:')
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.ele.me/restapi/v2/pois?'
place = input('请输入你的收货地址:')
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+'相关的位置信息:\n')
n=0
for address in address_json:
print(str(n)+'. '+address['name']+':'+address['short_address']+'\n')
n = n+1
address_num = int(input('请输入您选择位置的序号:'))
final_address = address_json[address_num]
restaurants_url = 'https://www.ele.me/restapi/shopping/restaurants?'
# 使用带有餐馆列表的那个XHR地址。
params = {'extras[]':'activities',
'geohash':final_address['geohash'],
'latitude':final_address['latitude'],
'limit':'24',
'longitude':final_address['longitude'],
'offset':'0',
'terminal':'web'
}
# 将参数封装,其中geohash和经纬度,来自前面获取到的数据。
restaurants_res = session.get(restaurants_url,params=params)
# 发起请求,将响应的结果,赋值给restaurants_res
restaurants = restaurants_res.json()
# 把response对象,转为json。
for restaurant in restaurants:
# restsurants最外层是一个列表,它可被遍历。restaurant则是字典,里面包含了单个餐厅的所有信息。
print(restaurant['name'])

参考答案和总结

参考答案:

选择语言
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.ele.me/restapi/eus/login/mobile_send_code'
tel = input('请输入手机号码:')
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.ele.me/restapi/eus/login/login_by_mobile'
code = input('请输入手机验证码:')
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.ele.me/restapi/v2/pois?'
place = input('请输入你的收货地址:')
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+'相关的位置信息:\n')
n=0
for address in address_json:
print(str(n)+'. '+address['name']+':'+address['short_address']+'\n')
n = n+1
address_num = int(input('请输入您选择位置的序号:'))
final_address = address_json[address_num]
restaurants_url = 'https://www.ele.me/restapi/shopping/restaurants?'
# 使用带有餐馆列表的那个XHR地址。
params = {'extras[]':'activities',
'geohash':final_address['geohash'],
'latitude':final_address['latitude'],
'limit':'24',
'longitude':final_address['longitude'],
'offset':'0',
'terminal':'web'
}
# 将参数封装,其中geohash和经纬度,来自前面获取到的数据。
restaurants_res = session.get(restaurants_url,params=params)
# 发起请求,将响应的结果,赋值给restaurants_res
restaurants = restaurants_res.json()
# 把response对象,转为json。
for restaurant in restaurants:
# restsurants最外层是一个列表,它可被遍历。restaurant则是字典,里面包含了单个餐厅的所有信息。
print(restaurant['name'])

下面讲一下会遇到的问题~

validate_token这个在哪里可以找到呢?





输入手机号码,点击获取 验证码后,在文件mobile_send_code的Preview里面





出现这样的错误keyerror:validate_token

或者:{'message': '账户存在风险,需要图形验证码', 'name': 'NEED_CAPTCHA'}





出现这个问题一般ip请求多次,一般第4次后,就可能引起饿了么的反爬机制,导致出现你的访问异常,结果是keyerror错误;也就是需要图形验证码;

在山腰的知识暂时是无法解决的,目前可以每天尝试几次,或者换个手机或者ip网络;例如热点;建议出现keyerror可以暂时运行跳过,后续再试;一天一般有3-4次机会

如果要通过图片验证,一般主流有4种方法:

1)打码平台付费打码

2)PIL库提取图片文字

3)第9关的selenium模拟

选择语言
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.ele.me/restapi/eus/v3/captchas'
param = {'captcha_str':input('手机号码')}
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()

找到图片验证码在network里的位置,像爬图片一样保存到本地,然后input模拟输入验证码

(*在网页中输入手机号,需要输入验证码,在network里的img里找到验证码所在的图片,在像第0关教的爬取图片一样爬到本地展示,在模拟input输入)

选择语言
import requests
url = 'https://h5.ele.me/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'])

补充:饿了么实现的参考博客

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

饿了吗里面那个查询地址的链接是在哪找到的?





饿了么搜索地址的请求里url做了修改,练习时以网页上实际的情况为准





一份总结:

就是这样一个代码,它能拿到给定位置附近的餐厅名。但它的潜力并不只是如此。

如果我们尝试加载饿了么官网的首页,能够找到一个xhr叫做cities,这个xhr里包含了全国两千多个城市的经纬度。

利用Python的geohash模块,你可以将经纬度数据,转化为geohash(当然,也可以将geohash转为经纬度,我也是用这种方式,发现我的默认geohash是深圳)。

那么在理论上,其实你可以通过这种方式,拿到全国餐厅的数据……

只要稍做扩展,它还能拿到许多数据:所有的餐厅名/电话号码/评分/品牌/经纬度/介绍/均价/月销量……

此时,这个爬虫就具备了商业价值,它能胜任许多数据分析的工作:选址策略、定价策略、差异化竞争、2B营销……

或许你会质疑自己能不能做到像我描述的这样厉害,不用怕,很快你就能够做到对此心中有数。

而在后续的关卡,当你学会反爬虫的应对策略、协程、Scrapy框架……你会变得像我说的那样强大。

新练习-大神快更文





困难(#fb5a5c)
cookies与session post与get json数据解析与提取 反爬虫应对策略

要求:

在本练习,我们会借助cookies的相关知识,使用Python登录小说网站,用代码的形式对热榜上的大神进行催更。

网站地址:https://www.xslou.com/

目的:

  1. 练习掌握cookies和session的用法
  1. 练习post和get请求
  1. 练习json数据的解析提取
  1. 反爬虫应对策略

知识点回顾

cookies与session

cookies是服务器为了标记用户,存储在用户本地的数据,它里面也保存了用户的登录信息,同时它有一定的时效性,过期就会失效。





session是会话过程中,服务器用来记录特定用户会话的信息。





session和cookies的关系:cookies里带有session的编码信息,服务器可以通过cookies辨别用户,同时返回和这个用户相关的特定编码的session。













代码示例如下:

选择语言
import requests,json
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'
}
#添加请求头,避免被反爬虫。
try:
#如果能读取到cookies文件,执行以下代码,跳过except的代码,不用登录就能发表评论。
cookies_txt = open('cookies.txt', 'r')
#以reader读取模式,打开名为cookies.txt的文件。
cookies_dict = json.loads(cookies_txt.read())
#调用json模块的loads函数,把字符串转成字典。
cookies = requests.utils.cookiejar_from_dict(cookies_dict)
#把转成字典的cookies再转成cookies本来的格式。
session.cookies = cookies
#获取会话下的cookies
except FileNotFoundError:
#如果读取不到cookies文件,程序报“FileNotFoundError”(找不到文件)的错,则执行以下代码,重新登录获取cookies,再评论。
url = 'https://wordpress-edu-3autumn.localprod.oc.forchange.cn/wp-login.php'
#登录的网址。
data = {'log': input('请输入你的账号:'),
'pwd': input('请输入你的密码:'),
'wp-submit': '登录',
'redirect_to': 'https://wordpress-edu-3autumn.localprod.forc.work/wp-admin/',
'testcookie': '1'}
#登录的参数。
session.post(url, headers=headers, data=data)
#在会话下,用post发起登录请求。
cookies_dict = requests.utils.dict_from_cookiejar(session.cookies)
#把cookies转化成字典。
cookies_str = json.dumps(cookies_dict)
#调用json模块的dump函数,把cookies从字典再转成字符串。
f = open('cookies.txt', 'w')
#创建名为cookies.txt的文件,以写入模式写入内容
f.write(cookies_str)
#把已经转成字符串的cookies写入文件
f.close()
#关闭文件
url_1 = 'https://wordpress-edu-3autumn.localprod.forc.work/wp-comments-post.php'
#文章的网址。
data_1 = {
'comment': input('请输入你想评论的内容:'),
'submit': '发表评论',
'comment_post_ID': '13',
'comment_parent': '0'
}
#评论的参数。
session.post(url_1, headers=headers, data=data_1)
#在会话下,用post发起评论请求。

post与get

post和get都可以带着参数请求,不过get请求的参数会在url上显示出来。但post请求的参数就不会直接显示,而是隐藏起来。

在post请求里,我们使用data来传递参数,其用法和params非常相像。

代码示例:

选择语言
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重新发起请求

步骤

题目要求

项目目标:在本练习,我们会借助cookies的相关知识,使用Python登录小说楼,爬取热榜小说,对作者进行催更。

网站地址:https://www.xslou.com/

【讲解】

在本练习,我们会借助cookies的相关知识,使用Python登录小说楼,爬取热榜小说,对作者进行催更。

网站地址:https://www.xslou.com/

分步讲解

在这一步,我会带领你完成“分析过程”,请务必完整阅读文档。

在下一步,我们会开始按步骤书写代码。

【讲解】

体验流程

想要对热榜的小说进行催更,我们首先需要用浏览器体验这个过程。

前往小说楼,手动找到热榜所在位置

  1. 随机对一部小说进行催更
  1. 最后,再用Python代码去模拟这个过程

进入热榜

首先,打开小说楼的排行榜页:https://www.xslou.com/top/allvisit_1/

打开【检查】工具,选择【Network】,勾选【Preserve log】(因为等会可能会有页面跳转,勾选上防止在跳转过程中请求被清空)。 { 【新增图片】

【原图链接:】



【原来的样式:】



【0】鼠标右键选中下拉菜单的“检查” 【1】选择Network 【2】勾选Preserve log





体验登录

1、然后我们可以随机点击其中一本小说,对其进行催更 (现在网页更新,已经没有催更功能了!建议同学们直接用下载小说来做练习)









2、此时,如果没有登录小说楼(或注册)的用户,会自动跳到小说楼的登录页面:https://www.xslou.com/login.php

也就是说,想要催更,我们必须通过登录呀~(模拟登陆!!!催更的步骤先不做!)





3、阅读该URL,很容易能够看出这个是一个登录页,因为有链接有个login(中文:登录)

4、输入账号和密码,同时查看Network,便会发现浏览器会携带着账号和密码发起Post请求。 { 【新增图片】

【原图链接:】







获取催更链接(换成下载小说链接)

1、完成登录之后,页面会跳转到催更的页面,提示催更成功 



通过翻找Network,我们定位到,催更的请求是就是当前的url:https://www.xslou.com/modules/article/usercui.php?id=xxx { 【新增图片】

【原图链接:】



} 



该请求只需要一个参数:id(书籍的id)

注意:该链接限制了每天催更不能超过5次,也就是说该链接的请求不能超过5次

获取书籍id

1、进入小说热门列表页面:https://www.xslou.com/top/allvisit_1/右键检查, 发现该页面的数据就在第0个请求当中。

2、模拟催更书籍《纯阳武神》时,拿到的id是9356, 不过这个id到底从哪里来的? 要么,它藏在了HTML网页当中; 要么,它就是在请求的时候,后台下发的。 可先在Elements搜索一下该id,看它在不在HTML里。 (【搜索快捷键】win:ctrl+f | mac:command+f) { 【新增图片】

【原图链接:】

} 



3、经过分析,发现id确实藏在了HTML页面的链接当中:https://www.xslou.com/yuedu/9356/

4、下一步就是将数字9356从链接中分离出来,方法有很多,老师这里只讲解过滤器fliter过滤数字

选择语言
link = 'https://www.xslou.com/yuedu/9356/'
# 字符串link过滤出数字id(9356)
id_list = list(filter(str.isdigit,link))
book_id = ''.join(book_id)
# 步骤解析:1、filter()过滤数字 2、filter对象转列表 3、列表转字符串
# filter(str.isdigit,字符串)
# 第一个参数用来判断字符串的单个元素是否是数字,数字保留
# filter()返回的是对象,需要用list()函数转换成列表
# ''.join(列表)将列表转换成字符串

思考实现方案

所以正确的流程应该是:

  • 模拟登录获取cookies
  • 拿到书籍的id
  • 使用id参数和cookies请求催更

注:其中,前两步可以顺序调换。

代码实现

【讲解】

下面,我将带你一步步完成代码。

一、使用session和cookies模拟登录

体验登录:https://www.xslou.com/login.php

模拟登录参考示例:

选择语言
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 = ' https://wordpress-edu-3autumn.localprod.oc.forchange.cn/wp-login.php'
# 登录的参数。
data = {'log': input('请输入你的账号:'),
'pwd': input('请输入你的密码:'),
'wp-submit': '登录',
'redirect_to': 'https://wordpress-edu-3autumn.localprod.forc.work/wp-admin/',
'testcookie': '1'}
#在会话下,用post发起登录请求。
session.post(url, headers=headers, data=data)

【代码题】

【预设代码】

# 小说楼登录请求:https://www.xslou.com/login.php

【解答】

选择语言
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
login_url = 'https://www.xslou.com/login.php'
# 登录的参数。
data = {'username':input('请输入你的账号:'),
'password':input('请输入你的密码:'),
'action':'login'}
result = session.post(login_url, headers=headers, data=data)

二、获取书籍id

想要请求催更XHR,我们需要拿到参数id,也就是书籍id

小说排行榜:https://www.xslou.com/top/allvisit_1/

提示1: 1. 本步骤不需要模拟登录 2. 网站的编码模式是gbk

提示2

选择语言
link = 'https://www.xslou.com/yuedu/9356/'
# 字符串link过滤出数字id(9356)
id_list = list(filter(str.isdigit,link))
book_id = ''.join(book_id)
# 步骤解析:1、filter()过滤数字 2、filter对象转列表 3、列表转字符串
# filter(str.isdigit,字符串)
# 第一个参数用来判断字符串的单个元素是否是数字,数字保留
# filter()返回的是对象,需要用list()函数转换成列表
# ''.join(列表)将列表转换成字符串

提示3:

选择语言
# 爬取链接html页面中a标签的链接以及内容
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

【代码题】

【预设代码】

# 本步骤不需要模拟登录

# 小说楼的排行榜:https://www.xslou.com/top/allvisit_1/

【解答】

选择语言
import requests
from bs4 import BeautifulSoup
hot_url = 'https://www.xslou.com/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和参数请求催更链接

将上述两组代码组合。

拿到cookies和参数,完成催更请求(不要超过5次)

我帮你预置了前两个代码,你可以在此基础上完成本关卡任务。

注意: 1. 请求url需要拼接书籍id 2. 请求时候别忘了添加请求头和cookies:cookies=session.cookies

【代码题】

【预设代码】

选择语言
# 将上述两组代码组合。拿到cookies和参数,完成催更请求。
# 我帮你预置了前两个代码,你可以在此基础上完成本关卡任务。
# 小说楼:https://www.xslou.com/
# 小说楼登录:https://www.xslou.com/login.php
# 小说楼的排行榜:https://www.xslou.com/top/allvisit_1/
# 小说楼催更:https://www.xslou.com/modules/article/usercui.php?id=
import requests
from bs4 import BeautifulSoup
login_url = 'https://www.xslou.com/login.php'
hot_url = 'https://www.xslou.com/top/allvisit_1/'
urge_url = 'https://www.xslou.com/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('请输入你的账号:'),
'password':input('请输入你的密码:'),
'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):
# 请求催更链接需要拼接book_id
# 请求需要带上headers和cookies
def main ():
login_cookies()
books = get_bookids()
print('--------热门书籍--------')
for k,v in books.items():
print(k,':',v)
book_id = input('请输入想要催更的书籍id:')
urge(book_id)
main()

【解答】

选择语言
import requests
from bs4 import BeautifulSoup
login_url = 'https://www.xslou.com/login.php'
hot_url = 'https://www.xslou.com/top/allvisit_1/'
urge_url = 'https://www.xslou.com/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('请输入你的账号:'),
'password':input('请输入你的密码:'),
'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('--------热门书籍--------')
for k,v in books.items():
print(k,':',v)
book_id = input('请输入想要催更的书籍id:')
urge(book_id)
main()

参考答案和总结

【讲解】

参考答案:

选择语言
# 小说楼:https://www.xslou.com/
# 小说楼登录:https://www.xslou.com/login.php
# 小说楼的排行榜:https://www.xslou.com/top/allvisit_1/
# 小说楼催更:https://www.xslou.com/modules/article/usercui.php?id=
import requests
from bs4 import BeautifulSoup
login_url = 'https://www.xslou.com/login.php'
hot_url = 'https://www.xslou.com/top/allvisit_1/'
urge_url = 'https://www.xslou.com/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('请输入你的账号:'),
'password':input('请输入你的密码:'),
'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('--------热门书籍--------')
for k,v in books.items():
print(k,':',v)
book_id = input('请输入想要催更的书籍id:')
urge(book_id)
main()

练习-自制翻译器-参考

第一步:分析问题,明确目标

实现功能:用户输入英文或中文,程序即可打印出来对应的译文。

【讲解】

我们在左边输入文字,那么浏览器会把输入的信息传输给服务器,再返回对应的内容。

文:

第二步:思考要用到的知识

【讲解】

实现一键翻译的功能,最简单的方案便是爬虫。在此,我们选择的网站是有道翻译。

你在左边输入文字,那么浏览器会把你输入的信息传输给服务器。再返回对应的内容。









这就是一个典型的Post操作。

我们在Headers也可以看到“Request Method: POST”哦~





在前几关练习我们用的都是Get方式请求,Post是另一种常见的方式,课上已经学过其用法,在此不多赘述。

__Get是向服务器发索取数据的一种请求,而Post是向服务器提交数据的一种请求__

虽然第八关我们主要讲的是Cookies~

__Cookies用于服务器实现会话,用户登录及相关功能时进行状态管理__

但这道题并不需要用到小饼干,因为不需要登录不需要账号密码等。

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

__注意哦__ ლ(╹◡╹ლ)

有道翻译有反爬虫机制,它使用了加密技术。如果你的程序报错,你可以通过搜索、查阅资料找到解决方案:尝试把访问的网址中“/translate_o”中的“_o”删除。

服务器返回的内容,是json的格式。我们可以用处理列表、处理字典的手段来提取翻译。

第三步:写代码

你可以在浏览器的[network]-[Headers]-[General]里找到需要访问的网址,在[network]-[Headers]-[From data]里找到需要上传的数据。

__再次注意哦__ ლ(╹◡╹ლ)

有道翻译有反爬虫机制,它使用了加密技术。如果你的程序报错,你可以通过搜索、查阅资料找到解决方案:尝试把访问的网址中“/translate_o”中的“_o”删除。

服务器返回的内容,是json的格式。我们可以用处理列表、处理字典的手段来提取翻译。

【解答】

选择语言
import requests,json
#调用了两个模块。requests负责上传和下载数据,json负责解析。
word = input('你想翻译什么呀?')
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
#使用post需要一个链接。
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的内容,以字典的形式记录在data内。
r = requests.post(url,data)
#post需要输入两个参数,一个是刚才的链接,一个是data,返回的是一个Response对象。
answer=json.loads(r.text)
#你可以自己尝试print一下r.text的内容,然后再阅读下面的代码。
print ('翻译的结果是:'+answer['translateResult'][0][0]['tgt'])

第四步:套层壳(小彩蛋,了解即可,感兴趣的话可以深入学习)

我们总会听到前端后端全栈,感觉神秘有高大上,你一定很好奇它们都是什么呀?

今天呢,我们就简单接触下前端~

有米有很期待呀(́>◞౪◟<‵)ノシ

前端,是一种GUI软件。而我们现在要用的是Python里的一个模块实现本地窗口的功能。

它就是Tkinter~

Tkinter 模块是 Python 的标准 Tk GUI 工具包的接口。

Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 MacOS系统里。

Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。

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

最后的代码大约是这个模样,注意阅读注释~

当然你可以在终端运行(复制)这些代码,观察效果~

【解答】

认真阅读注释,你也可以复制下来在你的IDE中运行下哦~

选择语言
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需要一个链接
        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的内容,以字典的形式记录在data内。
        r = requests.post(url, data)
        #post需要输入两个参数,一个是刚才的链接,一个是data,返回的是一个Response对象
        answer=json.loads(r.text)
        #你可以自己尝试print一下r.text的内容,然后再阅读下面的代码。
        result = answer['translateResult'][0][0]['tgt']
        return result
class Application(object):
    def __init__(self):
        self.window = Tk()
        self.fanyi = YouDaoFanyi()
        self.window.title(u'我的翻译')
        #设置窗口大小和位置
        self.window.geometry('310x370+500+300')
        self.window.minsize(310,370)
        self.window.maxsize(310,370)
        #创建一个文本框
        #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.smith.edu/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)
        #创建一个按钮
        #为按钮添加事件
        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)
        #翻译结果标题
        self.title_label = Label(self.window,text=u'翻译结果:')
        self.title_label.place(x=10,y=165)
        #翻译结果
        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',' ')
        #把这个值传送给服务器进行翻译
        result = self.fanyi.crawl(content)
        #将结果显示在窗口中的文本框中
        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',' ')
        #把这个值传送给服务器进行翻译
        result = self.fanyi.crawl(content)
        #将结果显示在窗口中的文本框中
        self.result_text.delete(0.0,END)
        self.result_text.insert(END,result)
        print(content)
    #清空文本域中的内容
    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()

练习-图灵机器人-参考

第一步:登录注册图灵机器人

注册登录,才能创建自己的图灵机器人。

根据帮助中心的“说明书”,我们可以了解如何运用这个新工具~

【讲解】

进入图灵机器人官网[http://www.tuling123.com/](http://www.tuling123.com/),戳进帮助中心。





就像打开玩具先看说明书一样,我们来看看官方文档怎么说怎么用~





在功能说明中,我们知道,首先得登录注册,用免费版本就可以了(当然~土豪请随意),创建机器人在“机器人设置”中,我们用的是第一个API接入





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

__API就是接口__,就是通道,负责一个程序和其他软件的沟通,本质是预先定义的函数,而我们不需要了解这个函数只是调用这个接口就可达到函数的效果。

好,接下来我们看下“API V2.0接入文档”.





接口说明:API接口可调用聊天对话、语料库、技能三大模块的语料。

很好,我们今天想做的聊天机器人用这个接口就刚巧合适~

同时,在使用说明中我们可以知晓:

首先创建post请求所需的json数据,然后向指定的接口发起post请求即可,而且从参数说明中可以看到,只有参数 perception 和 userinfo 才是必须的。

对于userid这个参数官方文档说的是:长度小于32,是用户的唯一标识,这里我们只要创建userid 是长度小于32的字符串即可,说明书已经看完啦,来,开始着手做准备工作!





那我们回到主页,注册登录





然后在机器人管理界面,创建图灵机器人,最多可以创建5个,由此得出对应的5个apikey。(实际上一个就够啦)

apikey是针对接口访问的授权方式。





准备工作做完啦,接下来想想该如何写代码

第二步:创建自己的聊天机器人

请求过程:首先创建post请求所需的json数据,然后向指定的接口发起post请求即可,

而且从参数说明中可以看到,只有参数 perception 和 userinfo 才是必须的

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

【提示】

userid = str(1)

1 可以替换成任何长度小于32的字符串哦 ~

apikey = str(‘A')

这里的A,记得替换成你自己的apikey哦~

对咯,还有件小事需要注意一下,有时候可能你的代码没有错,但最后显示加密错误,那是apikey过期了,不过没关系,不是可以最多创建5个机器人嘛,换一个apikey试试就好咯~

【解答】

选择语言
import requests
import json
userid = str(1)
# 1 可以替换成任何长度小于32的字符串哦 
apikey = str(''A)
# 这里的A,记得替换成你自己的apikey哦~
# 创建post函数
def robot(content):
    # 图灵api
    api = r'http://openapi.tuling123.com/openapi/api/v2'
    # 创建post提交的数据
    data = {
        'perception': {
            'inputText': {
                'text': content
                         }
                      },
        'userInfo': {
                    'apiKey': apikey,
                    'userId': userid,
                    }
    }
    # 转化为json格式
    jsondata = json.dumps(data)
    # 发起post请求
    response = requests.post(api, data = jsondata)
    # 将返回的json数据解码
    robot_res = json.loads(response.content)
    # 提取对话数据
    print(robot_res['results'][0]['values']['text'])
for x in range(10):
    content = input('talk:')
    # 输入对话内容 
    robot(content)
    if x == 10:
        break 
        # 十次之后就结束对话,数字可以改哦,你想几次就几次
#当然咯,你也可以加一些stopwords,只要说了这些词就可以终止聊天
while True:
    content = input('talk:')
    # 输入对话内容 
    robot(content)
    if content == 'bye':
    # 设置stopwords
        break
#但是,我觉得吧,喜欢和聊天机器人玩的都是话痨,所以,可以最后加个死循环,如下:
# 创建对话死循环
while True:
    # 输入对话内容
    content = input('talk:')
    robot(content)

这个练习可能会遇到的问题

1、api = r'http://openapi.tuling123.com/openapi/api/v2'  为什么要写成这种格式,而不是常规的网页?为啥有个r?

加r表示绝对字符串,这样里面的\就不会表达出其他的意思。r是保持字符串原始值的意思,就是说不对其中的符号进行转义。因为windows下的目录字符串中通常有斜杠'\',而斜杠在Python的字符串中有转义的作用。例如:\n表示换行如果路径中有\new就会被转义。加上r就是为了避免这种情况~

2、对话限制问题

目前图灵机器人免费用户对话限制由原先的100次限制剩3次!

练习-nlpir人工智能-参考

目前网站无法访问,这个练习不用做了哈~

第9关

练习-博客达人-参考

你需要做的事情是:

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

然后,在文章《未来已来(三)——同九义何汝秀》中,发表一个评论,这个评论中必须要带有“selenium”这个词。

博客登录页面:https://wordpress-edu-3autumn.localprod.forc.work/wp-login.php

答这道题的时候,使用可视模式会对运行结果有更直观的了解,如果你想看到浏览器的操作过程,建议你在本地写好练习答案,然后再复制到这里。

【提示】

使用`selenium`操作浏览器的方法,就和人一步一步操作的步骤是一样的:

1. 获取网页

2. 输入用户名与密码,点击登录

3. 点击《未来已来(三)——同九义何汝秀》文章标题,进入文章页面

4. 找到评论区,输入评论,点击发表评论

用到的知识点都是`selenium`提取数据的方法,以及操作元素的方法。

【解答】

特别提示:

从博客首页进入文章页面时,需要用到 find_element_by_partial_link_text 通过链接的部分文本获取超链接。

发表评论之后,不会再终端返回运行结果,记得去博客文章的页面去看看自己的评论有没有成功~

由于教学系统中与你本地的浏览器设置方法不同,我给你提供了两份答案,一份可以在课程系统中运行,一份可以在你的本地运行。

选择语言
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.webdriver import RemoteWebDriver
# 获取用户输入的评论内容
while True:
    comment_content = input('请输入你想要的评论的内容,按回车提交:')
    if comment_content == '':
        print('&' * 5, '评论内容不允许为空', '&' * 5)
    else:
        break
'''方法一:使用自己电脑上的浏览器'''
driver = webdriver.Chrome()  # 实例化浏览器对象
driver.get('https://wordpress-edu-3autumn.localprod.forc.work/wp-login.php')  # 访问页面
time.sleep(2)
'''方法二:使用教学系统的浏览器设置,只能在网页的在线编辑器上运行'''
# chrome_options = Options()  # 实例化Option对象
# chrome_options.add_argument('--headless')  # 对浏览器的设置
# driver = webdriver.Chrome('http://chromedriver.python-class-fos.svc:4444/wd/hub',
#                          chrome_options.to_capabilities())  # 声明浏览器对象
# driver.get('https://wordpress-edu-3autumn.localprod.forc.work/wp-login.php')  # 访问页面
# 定位到用户名输入框,输入用户名
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')
# 定位到登录按钮,并点击按钮
submit_btn = driver.find_element_by_id('wp-submit')
submit_btn.click()
time.sleep(2)
# 通过链接的部分文本定位到'《未来已来(三)——同九义何汝秀》'这篇文章
# 获取到该文章对应的a标签(超链接),并点击链接进入文章详情页
article_link = driver.find_element_by_partial_link_text('同九义何汝秀')
article_link.click()
# 进入文章详情页,定位到该页面下编写评论的文本框,输入内容
comment_area = driver.find_element_by_id('comment')
comment_area.send_keys(comment_content)
time.sleep(2)
# 定位到提交按钮,点击该按钮提交评论
comment_submit = driver.find_element_by_id('submit')
comment_submit.click()
# 评论成功10秒后关闭浏览器
time.sleep(10)
driver.close()
print('#' * 6, '评论成功,浏览器已关闭', '#' * 6)

练习-Python之禅-参考

题目要求

获取网站[你好,蜘蛛侠!](https://localprod.pandateacher.com/python-manuscript/hello-spiderman/)的Python之禅中文英对照文本。

需要通过两种方法获取:

- 只使用`selenium`

- `selenium`与`BeautifulSoup`配合

【讲解】

[你好,蜘蛛侠!](https://localprod.pandateacher.com/python-manuscript/hello-spiderman/)是一个动态网页,URL:https://localprod.pandateacher.com/python-manuscript/hello-spiderman/

Python之禅的内容没有存在网页源代码中,无法通过`requests.get()`与`BeautifulSoup`提取“Python之禅”的内容,不过,我们可以通过`selenium`获取到。

方法如下:

0. 使用`selenium`获取网页

1. 输入你喜欢的老师和助教,点击提交

2. 提取`Elements`中渲染完成的完整网页源代码中的,中英文对照的Python之禅

我在课堂讲解中带你做过前两步了,第三步正是你现在需要做的。

我们可以用两种方式完成它~

第一种方法:

只使用`selenium`。

第二种方法:

使用`selenium`配合`BeautifulSoup`。

第一种方法:selenium

这次我们要用`selenium`单独完成这个爬虫。获取数据、解析数据、提取数据这三个步骤全部都由`selenium`来完成,写代码吧~

【提示】

前面的步骤,在关卡课程中都已经讲过,现在要做的是,在它的基础之上,获取中英文的“Python之禅”内容。

中文和英文版的“Python之禅”都在同样的标签中。所以,需要先获取所有的`class_='content'`标签,然后再从中分别提取标题与正文。

具体的方法都写在了代码注释中。

由于教学系统中与你本地的浏览器设置方法不同,我给你提供了两份答案,一份可以在课程系统中运行,一份可以在你的本地运行。

【解答】

选择语言
# 下面是只能在爬虫课系统中运行的答案:
from selenium.webdriver.chrome.webdriver import RemoteWebDriver # 从selenium库中调用RemoteWebDriver模块
from selenium.webdriver.chrome.options import Options  # 从options模块中调用Options类
import time
chrome_options = Options() # 实例化Option对象
chrome_options.add_argument('--headless') # 把Chrome设置为静默模式
driver = RemoteWebDriver('http://chromedriver.python-class-fos.svc:4444/wd/hub', chrome_options.to_capabilities()) # 设置浏览器引擎为远程浏览器
chrome_options = Options() # 实例化Option对象
chrome_options.add_argument('--headless') # 把Chrome设置为静默模式
driver = RemoteWebDriver('http://chromedriver.python-class-fos.svc:4444/wd/hub', chrome_options.to_capabilities()) # 设置浏览器引擎为远程浏览器
driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面
time.sleep(2) # 暂停两秒,等待浏览器缓冲
teacher = driver.find_element_by_id('teacher') # 找到【请输入你喜欢的老师】下面的输入框位置
teacher.send_keys('必须是吴枫呀') # 输入文字
assistant = driver.find_element_by_name('assistant') # 找到【请输入你喜欢的助教】下面的输入框位置
assistant.send_keys('都喜欢') # 输入文字
button = driver.find_element_by_class_name('sub') # 找到【提交】按钮
button.click() # 点击【提交】按钮
time.sleep(1)
contents = driver.find_elements_by_class_name('content') # 定位到Python之禅所在的标签
for content in contents:
    title = content.find_element_by_tag_name('h1').text # 提取标题
    chan = content.find_element_by_tag_name('p').text # 提取正文
    print(title + '\n' + chan + '\n') # 打印标题与正文
driver.close()
选择语言
# 下面是只能在你的本地运行的答案:
from selenium import  webdriver # 从selenium库中调用webdriver模块
import time
driver = webdriver.Chrome() # 声明浏览器对象
driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面
time.sleep(2) # 暂停两秒,等待浏览器缓冲
teacher = driver.find_element_by_id('teacher') # 找到【请输入你喜欢的老师】下面的输入框位置
teacher.send_keys('必须是吴枫呀') # 输入文字
assistant = driver.find_element_by_name('assistant') # 找到【请输入你喜欢的助教】下面的输入框位置
assistant.send_keys('都喜欢') # 输入文字
button = driver.find_element_by_class_name('sub') # 找到【提交】按钮
button.click() # 点击【提交】按钮
time.sleep(1)
contents = driver.find_elements_by_class_name('content') # 定位到Python之禅所在的标签
for content in contents:
    title = content.find_element_by_tag_name('h1').text # 提取标题
    chan = content.find_element_by_tag_name('p').text # 提取正文
    print(title + '\n' + chan + '\n') # 打印标题与正文
driver.close()

第二种方法:selenium 与 BeautifulSoup配合

先用`selenium`获取到渲染完成的`Elements`中的网页源代码,然后,`BeautifulSoup`登场解析和提取数据。

【提示】

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

这是字符串对象的一个方法,它的意思是,把第一个参数的字符串用第二个参数的字符串替代。

【解答】

具体的方法都写在了代码注释中。

由于教学系统中与你本地的浏览器设置方法不同,我给你提供了两份答案,一份可以在课程系统中运行,一份可以在你的本地运行。

选择语言
# 下面是只能在爬虫课系统中运行的答案:
from selenium.webdriver.chrome.webdriver import RemoteWebDriver # 从selenium库中调用RemoteWebDriver模块
from selenium.webdriver.chrome.options import Options # 从options模块中调用Options类
from bs4 import BeautifulSoup
import time
chrome_options = Options() # 实例化Option对象
chrome_options.add_argument('--headless') # 把Chrome设置为静默模式
driver = RemoteWebDriver('http://chromedriver.python-class-fos.svc:4444/wd/hub', chrome_options.to_capabilities()) # 设置浏览器引擎为远程浏览器
driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面
time.sleep(2) # 暂停两秒,等待浏览器缓冲
teacher = driver.find_element_by_id('teacher') # 定位到【请输入你喜欢的老师】下面的输入框位置
teacher.send_keys('必须是吴枫呀') # 输入文字
assistant = driver.find_element_by_name('assistant') # 定位到【请输入你喜欢的助教】下面的输入框位置
assistant.send_keys('都喜欢') # 输入文字
button = driver.find_element_by_class_name('sub') # 定位到【提交】按钮
button.click() # 点击【提交】按钮
time.sleep(1) # 等待一秒
pageSource = driver.page_source # 获取页面信息
soup = BeautifulSoup(pageSource,'html.parser')  # 使用bs解析网页
contents = soup.find_all(class_='content') # 找到源代码Python之禅中文版和英文版所在的元素
for content in contents:  # 遍历列表
    title = content.find('h1').text # 提取标题
    chan = content.find('p').text.replace('  ','') # 提取Python之禅的正文,并且去掉文字前面的所有空格
    print(title + chan + '\n') # 打印Python之禅的标题与正文
driver.close()
# 下面是只能在你的本地运行的答案:
from selenium import  webdriver # 从selenium库总调用webdriver模块
import time
from bs4 import BeautifulSoup
driver = webdriver.Chrome() # 声明浏览器对象
driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面
time.sleep(2) # 暂停两秒,等待浏览器缓冲
teacher = driver.find_element_by_id('teacher') # 定位到【请输入你喜欢的老师】下面的输入框位置
teacher.send_keys('必须是吴枫呀') # 输入文字
assistant = driver.find_element_by_name('assistant') # 定位到【请输入你喜欢的助教】下面的输入框位置
assistant.send_keys('都喜欢') # 输入文字
button = driver.find_element_by_class_name('sub') # 定位到【提交】按钮
button.click() # 点击【提交】按钮
time.sleep(1) # 等待一秒
pageSource = driver.page_source # 获取页面信息
soup = BeautifulSoup(pageSource,'html.parser')  # 使用bs解析网页
contents = soup.find_all(class_='content') # 找到源代码Python之禅中文版和英文版所在的元素
for content in contents:  # 遍历列表
    title = content.find('h1').text # 提取标题
    chan = content.find('p').text.replace('  ','') # 提取Python之禅的正文,并且去掉文字前面的所有空格
    print(title + chan + '\n') # 打印Python之禅的标题与正文
driver.close()

第10关

练习-周末吃什么-参考

第一步:明确目标

先明确目标:我们曾在第3关爬取了下厨房网站中的“本周最受欢迎菜谱”,现在,我们完善这个程序,让程序在每个周五爬取数据,并把菜谱发送到我们的邮箱。

【讲解】

先明确目标:我们曾在第3关爬取了下厨房网站中的“本周最受欢迎菜谱”,现在,我们完善这个程序,让程序在每个周五爬取数据,并把菜谱发送到我们的邮箱。

该项目和第10关课堂的项目是非常相似的。

第二步:分析过程

再分析过程:这个程序一共分为三部分:爬虫、通知和定时。

【讲解】

这个程序一共分为三部分,知识我们都掌握了。

0.爬虫:爬取下厨房网站中本周最欢迎菜谱的菜名、链接、原材料。

1.通知:用smtplib、email库来发送邮件。

2.定时:用schedule和time库定时执行程序。

我们分别写出来,然后封装成函数。

先把每个程序写出来,然后拼装到一起;鉴于爬虫程序已经学过,就直接把代码提供给大家。

第三步:代码实现

接下来就是写代码啦。

0.爬虫:爬虫代码已经在课堂上学过,所以直接把爬虫代码提供给大家,并请大家先封装爬虫代码:

选择语言
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关所学的内容,下面提供代码给大家,但最好是回忆不起来再看;写完代码后请大家封装代码。

(仍然提醒同学们,学习系统会记录大家输入的内容。考虑到信息隐私的问题,大家不要在这里输入自己的邮箱密码或账号。因此,请你在本地运行邮件相关的代码)

选择语言
import smtplib 
from email.mime.text import MIMEText
from email.header import Header
#引入smtplib、MIMETex和Header
mailhost='smtp.qq.com'
#把qq邮箱的服务器地址赋值到变量mailhost上,地址应为字符串格式
qqmail = smtplib.SMTP()
#实例化一个smtplib模块里的SMTP类的对象,这样就可以调用SMTP对象的方法和属性了
qqmail.connect(mailhost,25)
#连接服务器,第一个参数是服务器地址,第二个参数是SMTP端口号。
#以上,皆为连接服务器。
account = input('请输入你的邮箱:')
#获取邮箱账号,为字符串格式
password = input('请输入你的密码:')
#获取邮箱密码,为字符串格式
qqmail.login(account,password)
#登录邮箱,第一个参数为邮箱账号,第二个参数为邮箱密码
#以上,皆为登录邮箱。
receiver=input('请输入收件人的邮箱:')
#获取收件人的邮箱。
content=input('请输入邮件正文:')
#输入你的邮件正文,为字符串格式
message = MIMEText(content, 'plain', 'utf-8')
#实例化一个MIMEText邮件对象,该对象需要写进三个参数,分别是邮件正文,文本格式和编码
subject = input('请输入你的邮件主题:')
#输入你的邮件主题,为字符串格式
message['Subject'] = Header(subject, 'utf-8')
#在等号的右边是实例化了一个Header邮件头对象,该对象需要写入两个参数,分别是邮件主题和编码,然后赋值给等号左边的变量message['Subject']。
#以上,为填写主题和正文。
try:
    qqmail.sendmail(account, receiver, message.as_string())
    print ('邮件发送成功')
except:
    print ('邮件发送失败')
qqmail.quit()
#以上为发送邮件和退出邮箱

2.定时:定时功能是第10关教的内容,代码如下,下面提供代码给大家,但最好回忆不起来再看;写完代码后请大家封装代码。

选择语言
import schedule
import time
#引入schedule和time
def job():
    print('I'm working...')
#定义一个叫job的函数,函数的功能是打印'I'm working...'
schedule.every(10).minutes.do(job)       #部署每10分钟执行一次job()函数的任务
schedule.every().hour.do(job)            #部署每×小时执行一次job()函数的任务
schedule.every().day.at('10:30').do(job) #部署在每天的10:30执行job()函数的任务
schedule.every().monday.do(job)          #部署每个星期一执行job()函数的任务
schedule.every().wednesday.at('13:15').do(job)#部署每周三的13:15执行函数的任务
while True:
    schedule.run_pending()
    time.sleep(1) 

【解答】

老师提供的参考答案是这样的:

选择语言
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('请输入你的邮箱:')
password = input('请输入你的密码:')
receiver = input('请输入收件人的邮箱:')
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 = '''
        序号: %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= '亲爱的,本周的热门菜谱如下'+list_all
    message = MIMEText(content, 'plain', 'utf-8')
    subject = '周末吃个啥'
    message['Subject'] = Header(subject, 'utf-8')
    try:
        qqmail.sendmail(account, receiver, message.as_string())
        print ('邮件发送成功')
    except:
        print ('邮件发送失败')
    qqmail.quit()
def job():
    print('开始一次任务')
    list_all = recipe_spider()
    send_email(list_all)
    print('任务完成')
schedule.every().friday.at('18:00').do(job)#部署每周三的13:15执行函数的任务
while True:
    schedule.run_pending()
    time.sleep(1) 

练习-看个电影吧-参考

第一步:明确目标

先明确目标:每个周五,程序在豆瓣TOP250榜单中随机选取三部电影,然后去爬取三部电影的下载链接,并把链接发送到我们的邮箱。

【讲解】

先明确目标:每个周五,程序在豆瓣TOP250榜单中随机选取三部电影,然后去爬取三部电影的下载链接,并把链接发送到我们的邮箱。该项目和第10关课堂的是非常相似的。

第二步:分析过程

我们来看看这个项目的实现思路。

【讲解】

这个程序一共分为四部分:





0.电影榜单爬虫:爬取豆瓣电影Top250的榜单,并存储文件到本地。

1.电影链接爬虫:每周五读取榜单中的三部电影,然后去爬取电影的下载链接。

2.通知功能:再把爬到的链接以邮件的形式发送给自己。

3.定时功能:用schedule和time库定时执行程序。

可以把4段代码分别写出来,然后封装成函数。鉴于爬虫程序已经做过练习,会直接把代码提供给大家。

电影榜单的爬虫是第3关课后的必做练习,电影链接的爬虫是第3关的选做练习,所以该练习的重点不会放在爬虫上。

第三步:代码实现(上)

【代码实现】又分为上中下。上、中分别把四段代码写出来,下是封装组装代码。

上:每周五晚上去豆瓣电影Top250的榜单上随机抽取3部,然后去下载这3部电影的链接,并打印出来。

先把两段爬虫的代码提供给大家,请大家先阅读,然后去写代码。(当然,你用你自己写的代码也是一样的,只要最后实现的功能和题目一致)

选择语言
#这是爬取豆瓣电影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()
选择语言
# 这是爬电影的下载链接的代码
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.ygdy8.com/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.ygdy8.com/'+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('没有'+movie+'的链接')

好,现在,我们需要先读取存储到本地的电影榜单的csv文件,然后用random库来随机抽取三部电影,再去下载相应的电影链接,并把电影链接打印出来。

请开始写代码吧。

【提示】

如果对这里的爬虫代码有疑惑,建议先完成第3关的练习和第6关的练习。

【解答】

选择语言
import requests,csv,random
from bs4 import BeautifulSoup
from urllib.request import quote
# 以上,为引入相应的库。
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的榜单,并存储为本地的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文件,并写入列表movielist中。
three_movies=random.sample(movielist,3)
# 以上,是从列表movielist中,随机抽取三部电影,取出来的是一个列表。
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.ygdy8.com/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.ygdy8.com/'+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='没有'+movie+'的下载链接'
        print(content)

第四步:代码实现(中)

接下来,我们来完成发送邮件,以及定时功能的代码,然后在下一步我们再封装、组合四段代码。

邮件代码是第10关所学的内容,下面提供代码给大家。

(仍然提醒同学们,学习系统会记录大家输入的内容。考虑到信息隐私的问题,大家不要在这里输入自己的邮箱密码或账号。因此,请你在本地运行邮件相关的代码)

选择语言
import smtplib
from email.mime.text import MIMEText
from email.header import Header
#引入smtplib、MIMETex和Header
mailhost='smtp.qq.com'
#把qq邮箱的服务器地址赋值到变量mailhost上,地址应为字符串格式
qqmail = smtplib.SMTP()
#实例化一个smtplib模块里的SMTP类的对象,这样就可以调用SMTP对象的方法和属性了
qqmail.connect(mailhost,25)
#连接服务器,第一个参数是服务器地址,第二个参数是SMTP端口号。
#以上,皆为连接服务器。
account = input('请输入你的邮箱:')
#获取邮箱账号,为字符串格式
password = input('请输入你的密码:')
#获取邮箱密码,为字符串格式
qqmail.login(account,password)
#登录邮箱,第一个参数为邮箱账号,第二个参数为邮箱密码
#以上,皆为登录邮箱。
receiver=input('请输入收件人的邮箱:')
#获取收件人的邮箱。
#content为上面的电影链接
#输入你的邮件正文,为字符串格式
message = MIMEText(content, 'plain', 'utf-8')
#实例化一个MIMEText邮件对象,该对象需要写进三个参数,分别是邮件正文,文本格式和编码
subject = '电影链接'
#输入你的邮件主题,为字符串格式
message['Subject'] = Header(subject, 'utf-8')
#在等号的右边是实例化了一个Header邮件头对象,该对象需要写入两个参数,分别是邮件主题和编码,然后赋值给等号左边的变量message['Subject']。
#以上,为填写主题和正文。
try:
    qqmail.sendmail(account, receiver, message.as_string())
    print ('邮件发送成功')
except:
    print ('邮件发送失败')
qqmail.quit()
#以上为发送邮件和退出邮箱
#定时功能是第10关教的内容,代码如下,下面提供代码给大家,但最好回忆不起来再看。
import schedule
import time
#引入schedule和time
def job():
    print('I'm working...')
#定义一个叫job的函数,函数的功能是打印'I'm working...'
schedule.every(10).minutes.do(job)    #部署每10分钟执行一次job()函数的任务
schedule.every().hour.do(job)          #部署每×小时执行一次job()函数的任务
schedule.every().day.at('10:30').do(job)#部署每天的10:30执行job()函数任务
schedule.every().monday.do(job)        #部署每个星期一执行job()函数的任务
schedule.every().wednesday.at('13:15').do(job)
#部署每周三的13:15执行函数的任务
while True:
    schedule.run_pending()
    time.sleep(1)  

【解答】

老师提供的参考答案是这样的:

选择语言
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.ygdy8.com/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.ygdy8.com/'+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='没有'+movie+'的下载链接'
            print(content)
    return contents
def send_movielink(contents):
    mailhost='smtp.qq.com'
    qqmail = smtplib.SMTP()
    qqmail.connect(mailhost,25)
    account = '×××××××××@qq.com' # 因为是自己发给自己,所以邮箱账号、密码都可以提前设置好,当然,也可以发给别人啦
    password = '×××××××××××××××' # 因为是自己发给自己,所以邮箱账号、密码都可以提前设置好,当然,也可以发给别人啦。
    qqmail.login(account,password)
    receiver='×××××××××@qq.com'  # 因为是自己发给自己,所以邮箱账号、密码都可以提前设置好,当然,也可以发给别人啦。
    message = MIMEText(contents, 'plain', 'utf-8')
    subject = '电影链接'
    message['Subject'] = Header(subject, 'utf-8')
    try:
        qqmail.sendmail(account, receiver, message.as_string())
        print ('邮件发送成功')
    except:
        print ('邮件发送失败')
    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)
(0)

相关推荐

  • [Python从零到壹] 四.网络爬虫之入门基础及正则表达式抓取博客案例

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  • Python爬虫破解有道翻译

    有道翻译是以异步方式实现数据加载的,要实现对此类网站的数据抓取,其过程相对繁琐,本节我以有道翻译为例进行详细讲解. 通过控制台抓包,我们得知了POST请求的参数以及相应的参数值,如下所示: post请 ...

  • 第 56 天:Python 爬虫之 urllib 包基本使用

    urllib 是一个 python 内置包,不需要额外安装即可使用,包里面包含了以下几个用来处理 url 的模块: urllib.request,用来打开和读取 url,意思就是可以用它来模拟发送请求 ...

  • 北邮人论坛爬虫实操:session替代cookies

    一.北邮人论坛 BBS式微的今天,北邮人论坛这个比水木清华差不多年纪的BBS.不但没有out,社区依旧很活跃.及时华丽上线移动版,依旧保持着生机,是国内高校排名前三的高校BBS,实在是难得. 应朋友需 ...

  • 文件包含

    一 进入页面发现一个大的滑稽脸,查看源代码,发现提示source.php 进入该页面,进行代码审计,又发现一个hint.php页面,进入发现提示 表明 flag 在这个文件中,且这个文件名暗示要使用四 ...

  • 爬虫精进第3关常见问题

    问题1.豆瓣电影无评论 豆瓣这一关的练习过程中,豆瓣网站的电影是不断更新的,有些豆瓣电影会出现没有评论语的情况: 报错信息"AttributeError: 'NoneType' object ...

  • 爬虫精进0

    第0关 练习-文章下载-参考 题目要求:获取文章[<HTTP状态响应码>]全部内容,并且打印出全文内容. 文本URL: https://localprod.pandateacher.com ...

  • 《六项精进》稻盛和夫告诉你,6个为人处世哲学,让你离成功更近

    文/铃兰 普通人能在事业上获得成功吗 普通人能在事业上获得成功吗?可能大部分人听了会摇头,因为在世俗的观念里. 一个人想要获得成功,必须要有强大的家族背景,有雄厚的经济基础,和优质的人脉关系,以及获得 ...

  • 【Python爬虫】:使用高性能异步多进程爬虫获取豆瓣电影Top250

    在本篇博文当中,将会教会大家如何使用高性能爬虫,快速爬取并解析页面当中的信息.一般情况下,如果我们请求网页的次数太多,每次都要发出一次请求,进行串行执行的话,那么请求将会占用我们大量的时间,这样得不偿 ...

  • 【Python爬虫】:破解网站字体加密和反反爬虫

    前言:字体反爬,也是一种常见的反爬技术,例如58同城,猫眼电影票房,汽车之家,天眼查,实习僧等网站.这些网站采用了自定义的字体文件,在浏览器上正常显示,但是爬虫抓取下来的数据要么就是乱码,要么就是变成 ...

  • 正知正见是一切精进的基础

    实证 答疑 科学实证 自主健康 正知正见是一切精进的基础 01 本来如如 本来就在 所以在这里我们要了解:第一,一切物质状态就是本来存在的,本来如如,本来就存在那里的.第二,我们对物质的使用是通过心物 ...

  • Python爬虫学习笔记(三)

    Cookies: 以抓取https://www.yaozh.com/为例 Test1(不使用cookies): 代码: import urllib.request# 1.添加URLurl = &quo ...

  • 每天反思,每天精进,【稻盛和夫一生的嘱托...

    每天反思,每天精进,[稻盛和夫一生的嘱托] →什么样的人才适合做领导? →人生六项精进 →什么是稻盛和夫心学? →人生的目的是什么? 全部原图分享给你,#关注我# #每天分享干货#

  • 日日精进,我的发展史

    由于假期原因,有几个项目留着节后在更新,也都是实操比较强的,这几天就碎碎念念随便写点什么. 我最开始接触这个行业是通过一个朋友,我们那时候在本地做一款棋牌游戏的推广,需要大量的同城流量,然后去拜访了一 ...