使用Python模拟腾讯第三方认证-篇4 [自动爬取分析及下载]
admin
2023-07-30 20:45:34
0

距离上次发布已经过去2个月之多,最近总结的时间越来越少,只能挤着来总结了。终于花了点时间将页面分析与下载工作完成。

工程准备

既然是自动爬取,尽量使用Scrapy框架,Scrapy的安装和使用请自行查询和学习。
对于HTML解析,推荐使用BeautifulSoup, 查询定位页面元素很方便。
使用Scrapy创建一个新的工程。
scrapy startproject jiekespider得到工程目录如下:

|--- scrapy.cfg
|    |--- jiekespider
|    |    |--- __init__.py
|    |    |--- items.py
|    |    |--- pipelines.py
|    |    |--- settings.py
|    |    |--- spiders
|    |    |    |---- __init__.py
|    |    |    |---- jiekespider.py # 手动创建此爬虫文件

然后需要更改两个文件,setting.py和items.py

setting.py

找到ITEM_PIPELINES,然后添加文件流水包处理,启用文件保存功能:

# Configure item pipelines
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   \'scrapy.contrib.pipeline.file.FilesPipeline\': 1,
}

在最后添加文件存储位置:

FILES_STORE = \"/home/bb/jike/\"

item.py

Scrapy框架中item定义了要处理的页面的数据结构,比如学院课程信息包含:视频地址,课程名称,课程时长等:
添加LessonInfo类:

class LessonInfo(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    lesson = scrapy.Field()
    unit = scrapy.Field()
    time = scrapy.Field()
    file_urls = scrapy.Field()
    files = scrapy.Field()

然后是关键文件,jikespider.py:

#!python
# coding=utf-8

# import the necessary packages
from jikespider.items import *
import scrapy

from bs4 import BeautifulSoup

class JikeSpider(scrapy.Spider):
    name = \"jike-spider\"
    start_urls = [\"http://www.jikexueyuan.com\"]
    dest_url = \"http://ke.jikexueyuan.com/zhiye/ios/\"
    logined = 0

    #继承与父类,默认会调用的回应处理
    def parse(self, response):
        if self.logined == 0:
            #登陆处理
        else:
              #处理主页面
            yield scrapy.Request(self.dst_url, self.parse_main)

如果单纯学习分析网页自动解析下载这部分功能足够了,使用这套框架只会把某一课程的第一节下载下来,因为不需要登陆验证。

登陆处理模块没有在此列出,但是前面章节已经做过演示及关键代码的展示,后续整理好后将放到Github上分享。

页面分析

入口页面

我们开始分析,首先确认页面入口,比如我使用了职业课程页面, 职业课程页面中选择IOS为启动URL,地址为:
http://ke.jikexueyuan.com/zhiye/ios/


Screenshot from 2016-01-25 13:03:19.png

查看源码可以看到从初级到高级的课程地址都分别在lesson-unit下,其中我们关心的时实际课程的URL,例如:

  1.iOS 开发的前世今生    

查看href项为http://www.jikexueyuan.com/course/1225.html,class为inner,则可将整个页面的课程URL查找出来:

def parse_main(self, response):
    soup = BeautifulSoup(response.body, \"lxml\")
    links = soup.find_all(\'a\', class_=\"inner\")

    #遍历课程,转向下级分析
    for link in links:
        l = link[\'href\']
        yield scrapy.Request(l,    self.parse_sub)

课程页面

现在可以进行分析课程页面http://www.jikexueyuan.com/course/1225.html, 查看源码,可以分析出以下关键信息:

  • 课程名称
  • 子章节名称,课时及URL
    子课程URL规律:
    学院的单个课程的URL与第一个子章节的URL很像,例如http://www.jikexueyuan.com/course/1225.html,第一章URL为http://www.jikexueyuan.com/course/1225_1.html?ss=1,第2章URL为http://www.jikexueyuan.com/course/1225_2.html?ss=1。所以可以考虑自己构建URL进行请求。
    另外,分析可以看到子章节是在

    块内,在一个text-box中会有课时的URL:

                                  

    课程介绍

    00:34

    本课时对课程内容做一简要介绍。

    那么子章节的URL就都可以从text-box中取出, 然后交给后面处理:

    def parse_sub(self, response):
      soup = BeautifulSoup(response.body, \"lxml\")
      lesson_box = soup.find_all(\'div\', class_=\'text-box\')
    
      for l in lesson_box:
          sub_l = l.h2.a[\'href\']
          yield scrapy.Request(sub_l,    self.parse_sub_info)

    子章节页面

    子章节页面类似这样的http://www.jikexueyuan.com/course/1225_1.html?ss=1地址,到来关键的课程页面,重申以下,至此我们想要的视频才算是能解析了。
    学院使用了video-js控件,并且支持HTML5的页面是包含source节点,这里浏览器看不到source节点就算了,还是抓取分析。
    整个子课程页面只使用一个播放器,故我们只关心source节点。
    另外课子章节名称和时长在text-box块内,课程名在lesson-teacher块内。

def parse_sub_info(self, response):
    f_r = \"00:00\"
    lesson = \"\"
    unit = \"\"
    file_urls = \"\"
    id = \"\"
    soup = BeautifulSoup(response.body, \"lxml\")

    #查找子课程信息:时长和名称
    lesson_box = soup.find_all(\'div\', class_=\'text-box\')
    for l in lesson_box:
        sub_l = l.h2.a[\'href\']
        print sub_l
        if (response.url == sub_l):  #因为多做了一次请求,只处理与本URL一致的课程信息
            unit = l.h2.a.string
            f_r = l.p.string
            break

    #查找课程视频地址
    source = soup.find_all(\'source\')
    if len(source):
        print source[0][\'src\']
        file_urls = source[0][\'src\']
    #查找课程名称
    lesson_teacher = soup.find_all(\'div\', class_=\'lesson-teacher\')
    if len(lesson_teacher) == 1:
        lesson = lesson_teacher[0].div.h2.string
        print lesson

    #子课程名添加编号,方便按顺序查看
    id = re.findall(\"\\_(.*)\\.html\", response.url)
    if len(id):
        unit = id[0] + unit

    #将课程信息推送到LessonInfo 处理单元(Item),后续保存和下载由Scapy自动完成
    if len(file_urls) and len(lesson):
        # yield the result
        yield LessonInfo(lesson=lesson, unit=unit, time=f_r, file_urls=[file_urls])

运行测试

使用scrapy crawl jike-spider -o video.json即将jike-spider初始化运行,-o为制定输出结果文件。
运行后Scrapy会将整个IOS课程子章节分别下载到设定的目录中,并且在当前目录生成抓取结果文件video.json。
如下内容:

[{\"files\": [{\"url\": \"http://cv4.jikexueyuan.com/a561bd397474a8449303864d26cfd96b/201601221755/ios/course_1225/01/video/c1225b_01_h264_sd_960_540.mp4\", \"path\": \"full/f165d19a878d1048df08f6cc9ba389ee1480bcf6.mp4\", \"checksum\": \"357b934b62b2f564bdfff1628f5b180c\"}], \"lesson\": \"iOS \\u5f00\\u53d1\\u7684\\u524d\\u4e16\\u4eca\\u751f\", \"unit\": \"1 iOS \\u5f00\\u53d1\\u7684\\u524d\\u4e16\\u4eca\\u751f\", \"file_urls\": [\"http://cv4.jikexueyuan.com/a561bd397474a8449303864d26cfd96b/201601221755/ios/course_1225/01/video/c1225b_01_h264_sd_960_540.mp4\"], \"time\": \"06:02\"},
{\"files\": [{\"url\": \"http://cv4.jikexueyuan.com/c9c10ce5ea141d5b0b347ef12b4bbf94/201601221755/course/1701-1800/1782/video/4830_b_h264_sd_960_540.mp4\", \"path\": \"full/3cfc51a0ec32349df5113d014fe2e64705af84e1.mp4\", \"checksum\": \"561e26ff5fe6e209726c077734fb4df0\"}], \"lesson\": \"\\u5229\\u7528 Map Kit \\u521b\\u5efa\\u5730\\u56fe\\u5e76\\u6dfb\\u52a0\\u81ea\\u5b9a\\u4e49\\u6807\\u8bc6\", \"unit\": \"1 Map Kit \\u57fa\\u7840\\u8bb2\\u89e3\", \"file_urls\": [\"http://cv4.jikexueyuan.com/c9c10ce5ea141d5b0b347ef12b4bbf94/201601221755/course/1701-1800/1782/video/4830_b_h264_sd_960_540.mp4\"], \"time\": \"04:02\"},
...

然后在设定的输出目录中可以看到文件在不断的下载,网速一般,可以喝杯咖啡了~

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
python绘图库Matplo... 本文简单介绍了Python绘图库Matplotlib的安装,简介如下: matplotlib是pyt...
Prometheus+Graf... 一,Prometheus概述 1,什么是Prometheus?Prometheus是最初在Sound...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...