由于平时看个电影,各种找资源太费劲了,而且好多磁力资源网站的广告那叫一个多啊,到处都是坑。一个不小心就跳转到什么 澳门金冠赌场,什么 性感荷官在线发牌的网站,整的搜个资源跟玩扫雷一下,真实令人头大。
所以我找了一些比较靠谱的磁力种子网站《【资源搜集】最新的磁力种子搜索网站汇总(亲测可用)》,用爬虫技术调用他们的搜索接口,直接提取他们的搜索结果,省的花时间花精力跟它们网页上的各种广告各种链接斗智斗勇。
我找了 17 个磁力种子网站,算下来应该是 17 篇爬虫教程,这个应该算是磁力种子爬虫系列吧,哈!如果有对这个系列爬虫感兴趣的朋友,请关注我的博客哦。
磁力种子爬虫系列第一篇,文章主要分为三大部分。
第一部分是关于网站页面的一些分析,主要是为了捋清楚思路,制定爬取策略。如果你对爬虫感兴趣,想入门学习爬虫,那么这部分你一定要认真看。
第二部分是代码实现部分,主要是讲解一些代码的编写,这部分中我会把爬虫的全部源码都贴出来。理论上讲,只要你配置好python环境,安装好相应的库,只要这个网站没崩,网址没变,源码贴上去可以直接运行爬取的。
第三部分是交流答疑部分,这一部分暂时先留着,文章发表之后,如果大家遇到了什么问题,可以评论留言或者加我微信讨论。一些重要的共性的问题,我会集中整理,统一回复在这里。
今天要爬的网站是 BT蚂蚁(http://www.btaxt.com/)。
先看一眼,这个网站长这样(如果到时候这个网址失效了,自己找的话千万小心别点进去钓鱼网站,叫 BT 蚂蚁的网站某度一搜出来一大把,但大部分都是假的)。
一、目标网站分析
按照惯例,先分析一波网页,伸手党如果懒得看,可以跳过直接去后面看代码实现部分。
1. 从网页上我们可以拿到哪些数据
根据上图,我们可以发现,在搜索结果中我们可以获得以下五个信息:
- 电影名称
- 时间,包括收录时间和最后活跃时间
- 活跃热度
- 文件大小
- 下载链接,包括磁力链接和迅雷链接
2. 确定网页中这些数据的加载方式
数据的加载一般有两种方式,一种是提前加载好存放在静态的网页中,另一种是采用 Ajax 技术动态地加载数据。
如果是前者的话,我们只需要发送一次请求,就可以获得该页面的全部数据。麻烦的点在于需要自行解析 HTML 内容,从大量的无用字符中提取自己需要的数据,较为繁琐。
如果是后者的话,发送一次请求只能获取一少部分的数据。需要抓包分析找到该网页向获取服务器获取数据的真正请求的格式,然后用爬虫模拟浏览器,不断向服务器发起请求来获取全部数据。这种情况麻烦之处在于分析,找到数据的真正请求接口比较不容易,尤其是对方网站采取了一定的反爬虫措施的话,会难上加难。好处就是,这种方法获取到的数据非常纯粹,一般以 json 格式存储,解析起来非常方便(有时甚至可能获得一些没有展示在网页上的有用信息哦,坏笑)。
对 BT 蚂蚁网站进行简单分析之后,发现该网站采用的是第一种数据加载方式。而且,
- 对于搜索结果,网站提供了 4 种排序方式,根据收录时间,根据活跃热度,根据最后活跃时间,根据文件大小。
- 每个页面展示 20 条搜索结果。
- 点击电影名称可跳转至详情页,但是关键数据在搜索结果页均有展示,无需跳转也可获取。
3. 我们如何解析网页提取这些数据
按下 F12 ,召唤出开发者工具,可以很方便的对照着分析网页结构。
如图所示,我们可以发现,在一个 <div id = "wall " > 的标签下,有 20 个并列的 <div class="search-item">...</div> 标签,而每一个标签,则对应着一条搜索结果。
展开其中一条搜索结果的标签,可以在其中找到我们需要的所有信息。到后面编码实现的时候,我们只需要照着这个结构去查找数据,就可以了。
4. 如何翻页获取所有数据以及 URL 的构造规则
由前面分析可知,搜索结果是分成多个页面的,每个页面只展示 20 条结果,要想获取所有数据,必须要知道它是怎么翻页的。
观察 URL 可知,每切换一页,页面的 URL 中的参数也会随之变化,如下所示
第一页:http://www.btaxt.com/search/钢铁侠-first-asc-1
由此可知, URL 中最后的数字代表的是页码,改变它的值,可以访问不同页码的网页。
不过,我们也看到了,URL 中除了末尾控制页码的数字之外,还有很多其他参数,它们是控制什么的呢?
这里我也不卖关子了,其实只要在网站上多点一点,多观察观察,很容易可以猜到他们的作用的。
其中有 4 个参数,“钢铁侠”,“first”,“asc”,“1”。
- “钢铁侠” 这个参数为磁力搜索的关键词,更换其他关键词可以查找其他电影
- “first” 这个参数表示,当前的搜索结果是按照收录时间排序的,同理,更改这个参数可以更换其他排序依据,hot 表示按照活跃热度排序,last 表示根据最后活跃排序,size 表示按照文件大小排序。
- “asc” 这个参数表示当前排序方式为升序,若想要降序排列,可更改为 desc。
- “1” 这个参数表示当前页码,更改这个数字可以实现翻页,注意的一点是,这个数字要在总页码范围之内,否则会报错。
根据这个规则,我们可以尝试构造一下一个新的 URL 练练手。
假如我希望查找关于 “蜘蛛侠” 的电影,搜索结果按活跃热度降序排列,它的第 2 页的 URL 为:
点击访问这个 URL,结果如预期所料,说明我们分析的是对的。
分析到这里,我们对这个网站的结构,内容都有了一定的了解,接下来,我们可以进行编码实现爬取啦
二、编码实现环节
依我的习惯,我将这个爬虫根据功能模块,拆分为了 5 个函数。
- fetchURL 函数,用来发起网络请求,
- getPageNum 函数,用来获取搜索结果的总页码,从而限定翻页参数的范围
- parseHTML 函数,用来解析网页,提取网页中的关键数据
- saveData 函数,用来将提取出的数据存储至本地文件中
- Main 函数,用来作为爬虫调度器。
1. 首先导入爬虫所需要的所有库
import requests
import bs4
import pandas as pd
import os
其中,requests 库用来处理与网络请求有关的事务,bs4(BeautifulSoup)用来解析 HTML 网页,pandas 和 os 用来进行本地文件的读写,以及数据保存。
2. 发起网络请求部分
def fetchURL(url):
'''
功能:访问 url 的网页,获取网页内容并返回
参数:目标网页的 url
返回:目标网页的 html 内容
'''
headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
r = requests.get(url,headers=headers)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(url)
return r.text
这个函数几乎可以通用了,你在写其他爬虫的时候,网络请求部分可以直接将这个函数 Copy 过去使用。
3. 解析网页内容部分
由于我们想要把所有页的数据都爬完,所以需要知道它到底有多少页。
虽然这个总页码也是在 HTML 中,本来我是写在 parseHTML 函数中解析获取的,但是为了让每个函数更加纯粹,我将获取总页码这个部分拆分出来,单独成为一个函数。
def getPageNum(html):
'''
功能:获取总页码数
'''
bsobj = bs4.BeautifulSoup(html,"html.parser")
pageLink = bsobj.find("div", attrs = {"class" : "bottom-pager"}).find_all("a")[-1]["href"]
page = int(pageLink.split("-hot-desc-")[1])
return page
获取总页码之后,对每一页的内容进行解析提取,得到想要的磁力链接数据,保存在一个数组中返回。
def parseHTML(html):
'''
功能:解析网页,提取需要的数据
参数:目标网页的 html 源码
返回:需要提取的数据
'''
#提取的数据有 title,date,hot,size,link
bsobj = bs4.BeautifulSoup(html,"html.parser")
movieList = bsobj.find_all("div", attrs = {"class" :"search-item"})
movieInfo = []
for item in movieList:
movieItem = []
title = item.find("div", attrs = {"class": "item-title"}).a.text
bar = item.find("div", attrs = {"class": "item-bar"}).find_all("span")
date = bar[0].b.text
hot = bar[1].b.text
size = bar[3].b.text
link = item.find("div", attrs = {"class": "item-bar"}).find_all("a")[0]["href"]
movieItem.append(title)
movieItem.append(date)
movieItem.append(hot)
movieItem.append(size)
movieItem.append(link)
movieInfo.append(movieItem)
return movieInfo
4. 保存文件
爬取到的数据需要保存在本地文件中(我这个一般保存在 csv 文件中,爬取完成后可以用 excel 打开和编辑)
def saveData(data, path, filename):
'''
功能:将 data 中的信息输出到文件中/或数据库中。
参数:data 将要保存的数据,path 保存路径,filename 保存的文件名
'''
# 如果没有该文件夹,则自动生成
if not os.path.exists(path):
os.makedirs(path)
dataframe = pd.DataFrame(data)
dataframe.to_csv(path + filename, encoding='utf_8_sig', mode='a', index=False, sep=',', header=False )
5. 主函数--爬虫调度器
所谓爬虫调度器,就是通过调度各个函数,用来启动和结束爬虫,根据用户输入的参数构造 URL,控制爬取的范围等等。
if __name__ == '__main__':
name = input("请输入要查找的电影名或番号:")
url = 'http://www.btakt.com/search/' + name + '-hot-desc-1'
html = fetchURL(url)
page = getPageNum(html)
print(page)
path = "Data/BT蚂蚁/"
filename = name + ".csv"
for index in range(0,page):
index += 1
print("-----------第" + str(index) + "页----------")
url = 'http://www.btakt.com/search/' + name + '-hot-desc-' + str(index)
html = fetchURL(url)
data = parseHTML(html)
saveData(data,path,filename)
在这里我简单解释一下整个爬虫的流程。
- 首先由用户输入要搜索的电影名或番号
- 根据用户的输入构造初始的 URL
- 解析网页获取总页数
- for 循环中,构造每一页的 URL ,发起网络请求,提取本页数据,保存数据。
- 如此循环,直至所有页的数据全部爬取完毕
6. 爬取结果展示
三、交流答疑区
2019年8月9日更新
我昨天看了一下,文章中使用的 BT蚂蚁的网址 http://www.btaxt.com/ 其实已经上不去了。导致爬虫程序也没有办法正常运行。
不过不必担心,只需要将代码中的网址,替换为 BT蚂蚁的最新网址,即可正常运行。
BT蚂蚁的最新域名我也找到了,是 http://www.btaut.com/ 。
同时,大家可以关注一下 https://blog.csdn.net/wenxuhonghe/article/details/95492491 这篇文章,我会定期检查更新的。
如果文章中有哪里没有讲明白,或者讲解有误的地方,欢迎在评论区批评指正,或者扫描下面的二维码,加我微信,大家一起学习交流,共同进步。