阅读 1807

学技术,从性趣开始

为什么这么说?

因为我想学Python很久了,听说它能做很多只有你想不到,没有它做不到的事。 然而事实很残酷,我是懒癌晚期患者,一直只专注在iOS开发当中(尽管做的也不咋好)。但是看到身边搞开发的朋友们都在努力去熟悉其他语言,我开始慌了。这时候我意识到我应该学习一门Objective-C & Swift之外的语言了。但前面说到了,我很懒,我不知道程序猿是不是都懒,学习一门新语言我必须给自己找到一个足够充分的理由,才能驱动我去做这件事。直到有天我无意间进入了某AV网站,发现页面清新脱俗,女优质量可以说很高了,就像下面这样。 为了确保我不被Cop请去喝茶,图片自行脑补吧

然后我就萌生了一个写Python爬虫,抓取该网站所有AV Star作品.torrent的想法。 这个想法达到了驱动我学Python这件事的要求。紧接着我就开始埋头苦干了。第一次写Python,我有点儿紧张,说的不对的地方请各位大神点击评论,留下您如杜蕾斯段子手般的文字,给我一个改过自新的机会。

第一步 - 安装Python

这个我就不说了,请移步廖雪峰的官方网站-Python教程,廖老师已经讲的很明了了。

第二步 - 去买一本书

由于我之前没用过Python,所以我先是在京东买了一本《用Python写网络爬虫》,让快递小哥先帮我运着。

第三步 - 看几个视频教程

相比文字教程,我更喜欢看视频教程,你想的没错,因为快,老师上课给你讲的都是例题,这样你下课才能通过例题去做习题,而不是上来就直接自己看例题,然后做习题。可能我笨吧。但这是我的学习方法。

我去慕课网逛了一圈,以x2的速度看完了两套免费的Python爬虫课程。 如果你之前像我一样一点儿没接触过Python,那么推荐你先看一下Python遇见数据采集。然后再看这个Python开发简单爬虫。不然你可能不太理解第二套课程中的设计模式。这是我踩的坑。

这两个课程都不难,而且时间也很短,用x2的速度看足以让你看懂爬虫爬取网页的一些套路。

第四步

根据两套视频课程的学习,相信你对爬取网页的一些套路已经有所了解,然后我们就可以通过两套视频学到的知识,来进行coding

Coding Your First Python Project

我的开发环境是Python3

➜  ~ python3
Python 3.6.0 (default, Feb 11 2017, 01:31:31)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
复制代码

两个教程本来讲的是urllib + BeautifulSoup的方式进行爬取,但是我一开始就遇到了问题。 就是要爬取的网站要用科学上网的方式才能访问,可是我用urllib中的request,无论我怎么设置proxy,都没有用。Google了很多,得到的答案大部分是用requests这个库来进行请求。(如果哪位大神有解决方案,我恳请您告诉我,先谢谢了)

于是我就先用了requests来进行编写

from bs4 import BeautifulSoup  # 引入 BeautifulSoup
import request                 # 引入 requests
import re                      # 引入 re
复制代码

然后我们定义一个url,还有一个headeruser-agent可以让你简单的伪装成浏览器

url = 'https://xxx.com/actress' #这个地址是AV Star的列表

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
    "Upgrade-Insecure-Requests": "1"
}

复制代码

由于我用ss科学上网,所以这里使用的是socks代理,地址你可以查看你的网络偏好设置中的代理Tab

proxies = {
            'http': 'socks5h://127.0.0.1:1080',
            'https': 'socks5h://127.0.0.1:1080'
    }
复制代码

紧接着我们就可以发起一个请求了

r = requests.get(url, proxies=proxies)   # 创建一个 requests 请求对象
soup = BeautifulSoup(r.content, 'html.parser', from_encoding='utf-8') # 创建一个 BeautifulSoup对象
复制代码

这个时候我们就可以去分析网页的结构了

箭头从上到下依次是

  • 该Star主页在网站中的地址
  • 图片链接
  • Star的名字

我们还知道,列表中每个item的class="card",我们就可以用soup对象对我们要的数据进行取出了

cardList = soup.find_all('div', class_="card") # 取出所有class="card"的内容
复制代码

然后我们对cardList进行遍历

starId = 0   # 初始化一个star id,方便我们对接下来数据库的写入
for card in cardList:

    sibling_soup = card

    starId = starId + 1 # starId自增

    # < p class ="card-header-title is-centered" > Star的名字在这个p标签里,我们用.find进行查找
    starName = sibling_soup.find('p', class_="card-header-title is-centered").get_text().strip()
    # .get_text()是获取这个p标签里的text(不包含其他标签),然后用.strip()对字符串进行去除前后空格的操作
    
    # 然后我们用re.compile去匹配sibling_soup对象中符合 /actress/ 的标签
    # 这里我偷了懒,因为网页中每个card里面只有一个a标签内容中含有 /actress/ ,所以我这样写了
    starPage = sibling_soup.find('a', href=re.compile(r"/actress/"))['href']
    # ['href']是拿到这个a标签中的链接
    # 拼接一下网站的域名
    starPage = "https://xxx.com" + starPage

    # < img class ="card-image" src="https://xxx.com/mono/movie/adult/mide558/mide558pl.jpg" >
    # 同样的方式去拿到图片的地址
    starImgUrl = sibling_soup.find('img', class_="card-image")['src']
复制代码

拿到了我们要的数据之后,就可以插入到数据库中了(关于数据库的安装与相关操作,可以观看上面推荐视频1)

# 打开本地数据库
staronnection = pymysql.connect(host='localhost', 
                                    user='root',
                                    db='Python',
                                    charset='utf8mb4')
    try:

        with staronnection.cursor() as cursor:
            sql = "insert into `AvStar`(`id`,`name`,`url`,`thumb`) values(%s, %s, %s, %s)"
            cursor.execute(sql, (starId, starName, starPage, starImgUrl))
            staronnection.commit()
    # 插入我们前面拿到的数据

    # 关闭数据库
    finally:
        staronnection.close()
复制代码

到现在,我们算是完成了60%了,接下来就是进入其中某个Star页面中一探究竟了。看一下页面结构,分析下我们需要的数据

图片中的红框自上而下是

  • 该作品的海报
  • 该作品的番号
  • 该作品.torrent文件的下载地址

ojbk,我们就要这些就行了

我们先只查找每个Star作品列表的前三页,

# 查找该Star的作品列表
    for num in [1, 2, 3]:

        newUrl = "%s?page=%d" % (starPage, num) # 拼接一下请求地址
        newResp = requests.get(newUrl, proxies=proxies) # 发起一个新请求
        newSoup = BeautifulSoup(newResp.content, 'html.parser', from_encoding='utf-8') # 创建一个新的BeautifulSoup对象

        # <div class="columns">
        avList = newSoup.find_all('div', class_="columns") # 拿到列表中每个作品对应的标签内容

        # 存种子下载链接
        for av in avList:

            avSoup = av
            # 拿到图片链接
            avThumb = avSoup.find('img', class_="image")["src"]
            
            # <h5 class="title is-4 is-spaced"/> 拿到番号
            avCode = avSoup.find('a', href=re.compile(r"/torrent/")).get_text().strip()
            
            # 拿到下载链接
            avAddress = avSoup.find('a', class_="button is-primary is-fullwidth")["href"]
            
            # 拼接下载链接
            avAddress = "https://xxx.com" + avAddress
            
            # 打开数据库,注意到这时我们在数据库中已经有一张AvStar的表用来存储Star的基础信息
            # 这里我们要新建一个表,用来存储每部作品的信息
            connection = pymysql.connect(host='localhost',
                                         user='root',
                                         db='Python',
                                         charset='utf8mb4')
            try:

                with connection.cursor() as cursor:
                    sql = "insert into `AvAddress`(`star_id`,`thumb`, `address`) values(%s, %s, %s)"
                    cursor.execute(sql, (starId, avThumb, avAddress))
                    connection.commit()


            finally:
                connection.close()
                # 关闭数据库
            
            # 这里我们发起一个请求 传入.torrent的下载地址
            fileResp = requests.get(avAddress, proxies=proxies)
            
            # 点击页面中的下载按钮,通过'检查'进行分析,见下图
            # 我们拿到Response Headers中的'Content-Disposition'
            # 自定义一个名字
            # 最后将文件写入到工程文件夹中
            if fileResp.headers.get('Content-Disposition'):
                # filename = "xxx.com_mide540_2.torrent
                filename = "xxx.com_" + avCode + ".torrent"
                open(filename, 'wb').write(fileResp.content)
                print("is downloaded" + filename + "onej" + "av" + ".com")
                
复制代码

Run 一下吧

至此,代码部分已经完成,我们run一下程序吧(想想还有点儿小激动)

➜  PythonProject git:(master) ✗ python3 xxx
复制代码

紧接着,我的工程目录下就添加了这么多文件,之后你再用迅雷打开.torrent,进行下载就行了。

总结

  1. 先分析你要抓取的网页地址、页面结构,查看其规律性,找到其中的套路
  2. 用最简单的方式拿到你想要的东西(这大概是Python这门语言的精髓所在了吧)

要解决的问题

  1. 插入数据库前应该判断一下数据库中有没有当前要插入的数据,如果有,就不插入。
  2. 我觉得应该加入一个sleep什么的,这样每抓一个页面就停一下,可以有效避免被封ip,当然了,小站可能没做这么多,但是大站貌似都会有反爬虫机制吧。
  3. 总感觉for的效率不是很高,我这里for3次,时间复杂度为,感觉应该开线程去跑,比如每个Star开一个线程去跑,这样会不会更好一些,但我还没学习到那里。接下来可能就哪里不会点哪里了。
  4. 最好是下载完.torrent之后自动打开下载器进行下载,这样白天上班时,家里的电脑跑着,晚上到家一看,电脑的硬盘爆了。哈哈哈哈

PS: 聪明的大神总能在代码中找到他们想要的,比如说:网址

`你离的越近看,你看到的东西越少` 
                --- 惊天魔盗团
复制代码
关注下面的标签,发现更多相似文章
评论

查看更多 >