抖音没有电脑版,刚学完scrapy,又懂一点django,哈!刚好可以搭建个简陋网页版抖音。

教程分为2部分,一部分是爬虫部分,另一部分是django网站部分。2部分都是些简单的基础知识,没啥高深的东西,适合初学者看看,下面是效果图。

题主的运行环境:

Windows10

python3.6

scrapy1.4

django2.1

python 通过分享链接抖音爬虫 抖音网页爬虫_python 通过分享链接抖音爬虫

python 通过分享链接抖音爬虫 抖音网页爬虫_scrapy爬虫_02

一、scrapy爬虫部分

1.先用fiddler对抖音app抓包,关于fiddler怎么抓包内容较多,大家自己百度下。不想自己抓包的直接使用我下面那个接口吧。

 

python 通过分享链接抖音爬虫 抖音网页爬虫_scrapy_03

 

这个category接口是爬取热门音乐和热门挑战的。题主使用的是下面这个 

python 通过分享链接抖音爬虫 抖音网页爬虫_python 通过分享链接抖音爬虫_04

这个接口每次请求随机返回20条左右视频信息,下面是评论信息接口

python 通过分享链接抖音爬虫 抖音网页爬虫_python 通过分享链接抖音爬虫_05

 

2.创建scrapy工程

 (1)打开cmd进入你想创建工程的目录输入(“douyin”就是工程的目录名,随意起名):scrapy startproject douyin

python 通过分享链接抖音爬虫 抖音网页爬虫_scrapy_06

 

 

(2)进入spider目录下创建爬虫,输入命令:scrapy genspider douyinSpider "a"   ,这表示创建一个名为douyinSpider的爬虫,名字随意但不要个工程名相同。“a”是爬虫域名的限制范围,这里不使用就随便写了个。

python 通过分享链接抖音爬虫 抖音网页爬虫_scrapy爬虫_07

(3)整个工程目录结构如下

python 通过分享链接抖音爬虫 抖音网页爬虫_ide_08

 

(4)编写douyinSpider爬虫文件,代码中都有注释了

# -*- coding: utf-8 -*-

import scrapy
from douyin.items import DouyinItem

import json
import jsonpath #jsonpath是用来方便解析大点的json文件的,用法大家百度下,挺简单的


class DouyinspiderSpider(scrapy.Spider):

    name = 'douyinSpider'

    #start_urls列表实际是调用start_requests函数来处理每个url的,这里我们重写下自己的start_requests
    def start_requests(self):

        #这是抖音的一个接口,每次请求这个url将会随机返回20条左右的抖音视频信息,count控制返回信息的多少,貌似25就是最大了。我们循环访问这个接口抓取数据
        url = "https://aweme.snssdk.com/aweme/v1/feed/?type=0&max_cursor=0&min_cursor=0&count=25&aid=1128"

        #这里循环爬取10次,dont_filter设置为True,表示不过滤重复url。因为我们每次都是请求同一个url,不设置dont_filter默认位False,只能爬取一次
        for i in range(1,10):
            yield scrapy.Request(url,dont_filter = True)

    def parse(self, response):
        json_response = json.loads(response.body_as_unicode())

        #找出返回文件中所有aweme_list下的文件,也就是抖音的视频信息列表,然后循环解析每一个视频信息,video_info就是1个抖音视频的所有信息
        aweme_list = jsonpath.jsonpath(json_response,"$..aweme_list")
        for aweme in aweme_list:
            for video_info in aweme:

                #digg_count是点赞数,筛选出点赞数大于10w的视频进行解析
                digg_count = video_info["statistics"]["digg_count"]
                if int(digg_count) > 10*10000:

                    #先找出aweme_id,aweme_id好像就是每个视频的唯一标识,我们这里要把aweme_id传入下面的comment_url这个接口爬取评论信息,
                    aweme_id = jsonpath.jsonpath(video_info,"$.statistics.aweme_id")
                    comment_url = "https://aweme.snssdk.com/aweme/v1/comment/list/?aweme_id={}&cursor=0&count=15&aid=1128".format(aweme_id[0])

                    #访问comment_url这个接口爬取每个视频的评论信息,调用parse_info函数解析,meta表示将video_info中的信息传递给parse_info函数
                    yield scrapy.Request(comment_url,callback=self.parse_info,meta={"video_info":video_info})
                else:
                    continue

    def parse_info(self,response):
        video_info = response.meta["video_info"] #接收上面parse函数传过来的video_info信息

        #这里只找出评论内容和评论点赞数,以列表形式返回
        comment_json = json.loads(response.body_as_unicode())
        comments = comment_json["comments"]
        comment_list = []
        for comment in comments:
            text = jsonpath.jsonpath(comment,'$..text') #评论内容
            digg_count = jsonpath.jsonpath(comment,'$..digg_count') #评论点赞数
            comment_list.append(text+digg_count) #text+digg_count是个列表,形如["小姐姐好漂亮",1888]

        #将每个抖音视频所有的信息传给init_item
        item = self.init_item(video_info,comment_list)
        yield item




    def init_item(self, video_info,comment_list):
        item = DouyinItem()

        #作者id
        item["author_user_id"] = video_info["author_user_id"]

        #视频aweme_id
        item["aweme_id"] = video_info["statistics"]["aweme_id"]

        #视频描述
        item["video_desc"] = video_info["desc"]

        #点赞数
        item["digg_count"] = video_info["statistics"]["digg_count"]

        #分享数
        item["share_count"] = video_info["statistics"]["share_count"]

        #评论数
        item["comment_count"] = video_info["statistics"]["comment_count"]

        #评论列表
        item["comment_list"] = comment_list

        #分享链接
        item["share_url"] = video_info["share_url"]

        #封面图链接列表,这里只取一个
        item["origin_cover"] = video_info["video"]["origin_cover"]["url_list"][0]

        #视频播放地址列表,这里只取一个并去掉多余参数
        item["play_addr"] = video_info["video"]["play_addr"]["url_list"][0].split("&line")[0]

        #视频下载地址列表,这里只取一个并去掉多余参数
        download_addr = video_info["video"]["download_addr"]["url_list"][0].split("&line")[0]
        item["download_addr"] = download_addr

        return item

(5)items文件

# -*- coding: utf-8 -*-

import scrapy

class DouyinItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    author_user_id = scrapy.Field()
    video_desc = scrapy.Field()
    aweme_id = scrapy.Field()
    play_addr = scrapy.Field()
    download_addr = scrapy.Field()
    origin_cover = scrapy.Field()
    comment_info = scrapy.Field()
    comment_list = scrapy.Field()
    digg_count = scrapy.Field()
    comment_count = scrapy.Field()
    share_count = scrapy.Field()
    share_url = scrapy.Field()

(6)pipelines文件,题主这里使用的是mysql数据库,需要安装pymysql库。解析json文件的jsonpath库

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html

import pymysql
import datetime

class DouyinPipeline(object):

    #初始化连接MySQl数据库,这里charset一定要设置为utf8mb4,这样才可以存储表情符号,抖音中是有很多表情符号的,创建数据库时也要编码设置为utf8mb4。下面passwd输入自己的密码
    def __init__(self):
        self.connect = pymysql.connect(
            host = "127.0.0.1",
            port = 3306,
            db = "douyin",
            user = "root",
            passwd = "123456",
            charset = 'utf8mb4',
            use_unicode = True
            )
        self.cursor = self.connect.cursor()
    print("连接数据库成功,正在存入数据库...")


    def process_item(self, item, spider):

        #执行sql语句,判断数据库中是否有此条视频信息,没有就插入,有就跳过,这里跳过没有更新数据库,因为更新也就更新下评论内容,这里就不更新了
        sql = "SELECT aweme_id FROM douyin_info WHERE aweme_id = {};".format(item['aweme_id'])
        status = self.cursor.execute(sql)
        if status == 0:
            self.cursor.execute(
                """insert into douyin_info(create_time,author_user_id, aweme_id, video_desc, digg_count ,share_count, comment_count,comment_list,share_url,origin_cover,play_addr,download_addr)
                value (%s,%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
                (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                 str(item['author_user_id']),
                 item['aweme_id'],
                 item['video_desc'],
                 item['digg_count'],
                 item['share_count'],
                 item['comment_count'],
                 str(item['comment_list']),
                 item['share_url'],
                 str(item['origin_cover']),
                 str(item['play_addr']),
                 str(item['download_addr'])
                 ))
            self.connect.commit()
        else:pass
        return item

    def close_spider(self,spider):
        self.connect.close()

(7)settings文件

# -*- coding: utf-8 -*-

BOT_NAME = 'douyin'

SPIDER_MODULES = ['douyin.spiders']
NEWSPIDER_MODULE = 'douyin.spiders'

USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60 MicroMessenger/6.5.18 NetType/WIFI Language/en'
ITEM_PIPELINES = {
   'douyin.pipelines.DouyinPipeline': 300,
}

(8)打开mysql数据库创建数据库,数据库名为douyin,这里推荐使用navicat,字符集一定要设置为utf8mb4才可以存储表情符号

python 通过分享链接抖音爬虫 抖音网页爬虫_python 通过分享链接抖音爬虫_09

(9)创建表,表名为douyin_info

CREATE TABLE douyin_info (
    auto_id INT NOT NULL primary key AUTO_INCREMENT,
    create_time DateTime NOT NULL,
    author_user_id VARCHAR(50),
    aweme_id VARCHAR(100),
    digg_count INT,
    video_desc VARCHAR(150),
    share_count INT,
    comment_count INT,
    comment_list TEXT,
    share_url VARCHAR(100),
    origin_cover VARCHAR(100),
    play_addr VARCHAR(100),
    download_addr VARCHAR(100));

 

(10)一切大功告成,打开cmd进入项目目录输入:scrapy crawl douyinSpider 就开始爬取数据了

python 通过分享链接抖音爬虫 抖音网页爬虫_scrapy_10