作者/分享人:张杨,热爱技术分享,活跃于今日头条和腾讯课堂,开设的《Python3网络爬虫入门》、《Python开发课程》等专栏受到好评。
一、前言
网络小说下载(静态网站)
爱奇艺VIP视频下载
二、网络爬虫简介
1. 审查元素
我们可以看到,右侧出现了一大推代码,这些代码就叫做HTML。什么是HTML?举个容易理解的例子:我们的基因决定了我们的原始容貌,服务器返回的HTML决定了网站的原始容貌。
为啥说是原始容貌呢?因为人可以整容啊!扎心了,有木有?那网站也可以"整容"吗?可以!请看下图:
可以看到,浏览器为我们自动定位到了相应的HTML位置。将下图中的password属性值改为text属性值(直接在右侧代码处修改):
就这样,浏览器"记住的密码"显现出来了:
2. 简单实例
urllib库是python内置的,无需我们额外安装,只要安装了Python就可以使用这个库。
requests库是第三方库,需要我们自己安装。
pip install requests
easy_install requests
# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':
target = 'http://gitbook.cn/'
req = requests.get(url=target)
print(req.text)
三、爬虫实战
1. 小说下载
# -*- coding:UTF-8 -*-
import requests
if __name__ == '__main__':
target = 'http://www.biqukan.com/1_1094/5403177.html'
req = requests.get(url=target)
print(req.text)
pip install beautifulsoup4
easy_install beautifulsoup4
<div id="content", class="showtxt">
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://www.biqukan.com/1_1094/5403177.html'
req = requests.get(url = target)
html = req.text
bf = BeautifulSoup(html)
texts = bf.find_all('div', class_ = 'showtxt')
print(texts)
<div id="content", class="showtxt">
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://www.biqukan.com/1_1094/5403177.html'
req = requests.get(url = target)
html = req.text
bf = BeautifulSoup(html)
texts = bf.find_all('div', class_ = 'showtxt')
print(texts[0].text.replace('\xa0'*8,'\n\n'))
程序运行结果如下:
可以看到,我们很自然的匹配到了所有正文内容,并进行了分段。我们已经顺利获得了一个章节的内容,要想下载正本小说,我们就要获取每个章节的链接。我们先分析下小说目录,URL:http://www.biqukan.com/1_1094/
<div class="listmain">
<dl>
<dt>《一念永恒》最新章节列表</dt>
<dd><a href="/1_1094/15932394.html">第1027章 第十道门</a></dd>
<dd><a href="/1_1094/15923072.html">第1026章 绝伦道法!</a></dd>
<dd><a href="/1_1094/15921862.html">第1025章 长生灯!</a></dd>
<dd><a href="/1_1094/15918591.html">第1024章 一目晶渊</a></dd>
<dd><a href="/1_1094/15906236.html">第1023章 通天道门</a></dd>
<dd><a href="/1_1094/15903775.html">第1022章 四大凶兽!</a></dd>
<dd><a href="/1_1094/15890427.html">第1021章 鳄首!</a></dd>
<dd><a href="/1_1094/15886627.html">第1020章 一触即发!</a></dd>
<dd><a href="/1_1094/15875306.html">第1019章 魁祖的气息!</a></dd>
<dd><a href="/1_1094/15871572.html">第1018章 绝望的魁皇城</a></dd>
<dd><a href="/1_1094/15859514.html">第1017章 我还是恨你!</a></dd>
<dd><a href="/1_1094/15856137.html">第1016章 从来没有世界之门!</a></dd>
<dt>《一念永恒》正文卷</dt>
<dd><a href="/1_1094/5386269.html">外传1 柯父。</a></dd>
<dd><a href="/1_1094/5386270.html">外传2 楚玉嫣。</a></dd>
<dd><a href="/1_1094/5386271.html">外传3 鹦鹉与皮冻。</a></dd>
<dd><a href="/1_1094/5403177.html">第一章 他叫白小纯</a></dd>
<dd><a href="/1_1094/5428081.html">第二章 火灶房</a></dd>
<dd><a href="/1_1094/5433843.html">第三章 六句真言</a></dd>
<dd><a href="/1_1094/5447905.html">第四章 炼灵</a></dd>
</dl>
</div>
http://www.biqukan.com/1_1094/5403177.html
<a href="/1_1094/5403177.html">第一章 他叫白小纯</a>
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://www.biqukan.com/1_1094/'
req = requests.get(url = target)
html = req.text
div_bf = BeautifulSoup(html)
div = div_bf.find_all('div', class_ = 'listmain')
print(div[0])
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
server = 'http://www.biqukan.com/'
target = 'http://www.biqukan.com/1_1094/'
req = requests.get(url = target)
html = req.text
div_bf = BeautifulSoup(html)
div = div_bf.find_all('div', class_ = 'listmain')
a_bf = BeautifulSoup(str(div[0]))
a = a_bf.find_all('a')
for each in a:
print(each.string, server + each.get('href'))
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests, sys
"""
类说明:下载《笔趣看》网小说《一念永恒》
Parameters:
无
Returns:
无
Modify:
2017-09-13
"""
class downloader(object):
def __init__(self):
self.server = 'http://www.biqukan.com/'
self.target = 'http://www.biqukan.com/1_1094/'
self.names = [] #存放章节名
self.urls = [] #存放章节链接
self.nums = 0 #章节数
"""
函数说明:获取下载链接
Parameters:
无
Returns:
无
Modify:
2017-09-13
"""
def get_download_url(self):
req = requests.get(url = self.target)
html = req.text
div_bf = BeautifulSoup(html)
div = div_bf.find_all('div', class_ = 'listmain')
a_bf = BeautifulSoup(str(div[0]))
a = a_bf.find_all('a')
self.nums = len(a[15:]) #剔除不必要的章节,并统计章节数
for each in a[15:]:
self.names.append(each.string)
self.urls.append(self.server + each.get('href'))
"""
函数说明:获取章节内容
Parameters:
target - 下载连接(string)
Returns:
texts - 章节内容(string)
Modify:
2017-09-13
"""
def get_contents(self, target):
req = requests.get(url = target)
html = req.text
bf = BeautifulSoup(html)
texts = bf.find_all('div', class_ = 'showtxt')
texts = texts[0].text.replace('\xa0'*8,'\n\n')
return texts
"""
函数说明:将爬取的文章内容写入文件
Parameters:
name - 章节名称(string)
path - 当前路径下,小说保存名称(string)
text - 章节内容(string)
Returns:
无
Modify:
2017-09-13
"""
def writer(self, name, path, text):
write_flag = True
with open(path, 'a', encoding='utf-8') as f:
f.write(name + '\n')
f.writelines(text)
f.write('\n\n')
if __name__ == "__main__":
dl = downloader()
dl.get_download_url()
print('《一年永恒》开始下载:')
for i in range(dl.nums):
dl.writer(dl.names[i], '一念永恒.txt', dl.get_contents(dl.urls[i]))
sys.stdout.write(" 已下载:%.3f%%" % float(i/dl.nums) + '\r')
sys.stdout.flush()
print('《一年永恒》下载完成')
二. 爱奇艺VIP视频下载
http://api.xfsub.com/index.php?url=[播放地址或视频id]
http://api.xfsub.com/index.php?url=http://www.iqiyi.com/v_19rr7qhfg0.html#vfrm=19-9-0-1
我们可以看到,有用的请求并不多,我们逐条分析。我们先看第一个请求返回的信息。
可以看到第一个请求是GET请求,没有什么有用的信息,继续看下一条。
我们看到,第二条GET请求地址变了,并且在返回的信息中,我们看到,这个网页执行了一个POST请求。POST请求是啥呢?它跟GET请求正好相反,GET是从服务器获得数据,而POST请求是向服务器发送数据,服务器再根据POST请求的参数,返回相应的内容。这个POST请求有四个参数,分别为time、key、url、type。记住这个有用的信息,我们在抓包结果中,找一下这个请求,看看这个POST请求做了什么。
xfsub_api\/url.php?key=02896e4af69fb18f70129b6046d7c718&time=1505724557&url=http%3A%2F%2Fwww.iqiyi.com%2Fv_19rr7qhfg0.html&type=&xml=1
xfsub_api/url.php?key=02896e4af69fb18f70129b6046d7c718&time=1505724557&url=http://www.iqiyi.com/v_19rr7qhfg0.html&type=&xml=1
http://api.xfsub.com/xfsub_api\url.php?key=02896e4af69fb18f70129b6046d7c718&time=1505724557&url=http://www.iqiyi.com/v_19rr7qhfg0.html&type=&xml=1
http://disp.titan.mgtv.com/vod.do?fmt=4&pno=1121&fid=1FEA2622E0BD9A1CA625FBE9B5A238A6&file=/c1/2017/09/06_0/1FEA2622E0BD9A1CA625FBE9B5A238A6_20170906_1_1_705.mp4
用正则表达式匹配到key、time、url等信息。
根据匹配的到信息发POST请求,获得一个存放视频信息的url。
根据这个url获得视频存放的地址。
根据最终的视频地址,下载视频。
思路已经给出,希望喜欢爬虫的人可以在运行下代码之后,自己重头编写程序,因为只有经过自己分析和测试之后,才能真正明白这些代码的意义。上述代码运行结果如下:
urlretrieve()有三个参数,第一个url参数是视频存放的地址,第二个参数filename是保存的文件名,最后一个是回调函数,它方便我们查看下载进度。代码量不大,很简单,主要在于分析过程。代码运行结果如下:
下载速度挺快的,几分钟视频下载好了。
三、总结
本场 Chat 讲解的实战内容,均仅用于学习交流,请勿用于任何商业用途!
爬虫时效性低,同样的思路过了一个月,甚至一周可能无法使用,但是爬取思路都是如此,完全可以自行分析。
本次实战代码,均已上传我的Github,欢迎Follow、Star:
https://github.com/Jack-Cherish/python-spider
如有问题,请留言。如有错误,还望指正,谢谢!
通知一下
你还在犹豫什么?加我助理老师,每晚八点半,发你课题通知你听课!
学完Python的就业前景
今天的内容就给大家分享在这里,今天没有所谓的妹纸来给大家值班。还是我,一直在后台给大家码字分享的张杨。其实每天在朋友圈还是在QQ群,各种平台,都会有很多的粉丝来私信我,想跟着我学Python,很多人大多数也是问问,我也是简简单单的应付一下,因为很多人在和我聊的第一感觉,我就能感觉这个人是不是真正的想学习Python,一般真真正正想学习Python的同学,他都很热情,对代码和程序充满了兴趣。在后台找到我的时候都是给我码了很长的一段字,这让我很欣慰,我也很高兴,看见你真正想学习的态度,其实很多时候,成长只是一个学习,一个态度的问题,而简简单单的一个态度就能看见你对这件事物的认真程度。
我是张杨,人生苦短,我用Python,喜欢请点赞。