首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python小白使用爬虫提取豆瓣电视剧数据

Python小白使用爬虫提取豆瓣电视剧数据

作者头像
沈唁
发布2018-06-19 10:48:52
2.1K0
发布2018-06-19 10:48:52
举报
文章被收录于专栏:沈唁志沈唁志

我…我…我是看着好久没更新Python的文章了,于是我将魔爪伸向了Python来水一文

准备工作

在开始干爬虫之前你肯定要安装Python的环境,也就是Python语言的解释器,还有Python的编辑器,Pycharm。这些之前都有说过,可以参考之前的分类文章

为了能够敏捷而又不失优雅地完成这次操作,我慎(tou)重(lan)选择了直接进行实战演练,废话不多说,开干

分析豆瓣URL

写爬虫之前肯定是要分析链接的,不然你怎么去爬,而且爬取数据我们尽量去找一些返回json数据的URL,因为json更好处理数据,但是并不是所有的站点返回数据都是json

怎么找返回json的URL呢?

  1. 打开浏览器的抓包工具,查看网络请求,当然你也可以使用FD等这些专业的工具
  2. 把浏览器网页切换到手机版

国产剧 – 电视 – 豆瓣的URL:https://m.douban.com/tv/chinese

然后我们按下F12打开浏览器的抓包工具,查看network这一栏就可以看到有一条这样的请求

items?os=ios&for_mobile=1&callback=jsonp1&start=0&count=18&loc_id=108288&_=1527155131544

点击它,看它的Request URL:

https://m.douban.com/rexxar/api/v2/subject_collection/filter_tv_domestic_hot/items?os=ios&for_mobile=1&callback=jsonp1&start=0&count=18&loc_id=108288&_=1527155131544

我们会发现我们访问的URL跟他请求是URL不同,然后我们查看它的Response就会看到一些json数据

浏览器的抓包工具
浏览器的抓包工具

浏览器的抓包工具

美剧 – 电视 – 豆瓣的URL:https://m.douban.com/tv/american

美剧的Request URL:

https://m.douban.com/rexxar/api/v2/subject_collection/filter_tv_american_hot/items?os=ios&for_mobile=1&callback=jsonp1&start=0&count=18&loc_id=108288&_=1527154794289

分析一下这两个URL

/filter_tv_domestic_hot/是根据这个参数来判断电视剧的类型,strat的值也会变,这个表示我们已经获取的数量

请求这个URL能够返回一个json字符串,我们能够将它转换为一个Python字典,就能够从中提取数据了,但是我们发现这个请求返回的数据中有一个jsonp1,这个jsonp1中间包括的才是一个字典,而外面这个jsonp1并不是我们所需要的数据

数据带有jsonp1
数据带有jsonp1

数据带有jsonp1

无论在爬其他网站的时候还是爬豆瓣的时候,如果发现返回的数据包含这个jsonp1、jsonp2…99在前面的时候,说明它的URL参数包含callback=jsonp1,要解决这个问题的话,我们就将这个参数删除掉,就可以将响应变成一个非常完美的json字符串

处理后得到的json数据
处理后得到的json数据

处理后得到的json数据

构建代码

骚气的分析了这么多,下面开始代码,新建一个py文件

定义一个run方法,主要实现我们的逻辑,先写一下我们的思路

def run():
    #1.url_list 带请求的是临时地址
    #2.发送请求 获取响应
    #3.提取数据
    #4.保存

然后进行异常处理+请求数据

from retrying import retry

@retry(stop_max_attempt_number=3)
def _parse_url(url):
    print("*"*100)
    r = requests.get(url,headers=headers,timeout=5) #可能会超时报错
    assert r.status_code == 200 #可能会请求不成功报错
    return r.content.decode()

def parse_url(url):
    try:
        html = _parse_url(url)
    except Exception as e:
        print("报错了:",e)
        html = None
    return html

完整的代码如下

import json
import requests
from retrying import retry

headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
           "Referer":"https://m.douban.com/tv/american"}#referer 豆瓣新加的

@retry(stop_max_attempt_number=3)
def _parse_url(url):
    print("*"*100)
    r = requests.get(url,headers=headers,timeout=5) #可能会超时报错
    assert r.status_code == 200 #可能会请求不成功报错
    return r.content.decode()

def parse_url(url):
    try:
        html = _parse_url(url)
    except Exception as e:
        print("报错了:",e)
        html = None
    return html

def get_url_list():#1.url_list 带请求的是临时地址
    url_list = [
        {
            "url_temp":"https://m.douban.com/rexxar/api/v2/subject_collection/filter_tv_american_hot/items?os=ios&for_mobile=1&start={}&count=18",
            "country":"UK"
        },
        {
            "url_temp":"https://m.douban.com/rexxar/api/v2/subject_collection/filter_tv_english_hot/items?os=ios&for_mobile=1&start={}&count=18",
            "country": "US"
        },
       {
           "url_temp": "https://m.douban.com/rexxar/api/v2/subject_collection/filter_tv_domestic_hot/items?os=ios&for_mobile=1&start={}&count=18",
           "country": "China"
       }
    ]
    return url_list

def get_content_list(json_response):
    dict_response = json.loads(json_response)
    content_list = dict_response["subject_collection_items"]
    total_num = dict_response["total"]
    return  content_list,total_num

def save_content_list(content_list):
    for content in content_list:
        print(content)
        print("*"*100)


def run():
    #1.url_list 带请求的是临时地址
    url_list_temp = get_url_list()
    for temp in url_list_temp:
        num = 0
        total_num = 100
        while num<=total_num+18:
            url = temp["url_temp"].format(str(num))
            #2.发送请求 获取响应
            json_response = parse_url(url)
            #3.提取数据
            content_list,total_num = get_content_list(json_response)
            #4.保存
            for content in content_list: #添加国家信息
                content["country"] = temp["country"]
            save_content_list(content_list)
            num += 18



if __name__ == '__main__':
    run()

反爬虫一些问题

有时候可能爬取不出来数据,这就说明豆瓣进行了升级或者你的爬虫被封禁了

单个ip单个用户在短时间内请求网站数据过快,都会被豆瓣的反爬虫机制发现并判断为机器操作而封禁,解决的方法有几种

1.使用ip代理池,隔一段时间随机换一个ip

2.降低爬取速度,设置爬虫间隔时间

3.将爬取内容分块,分时间段爬取

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 准备工作
  • 分析豆瓣URL
  • 构建代码
  • 反爬虫一些问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档