爬虫入门级别教程(小白水平)第二弹

本次文章主要以例子来讲解爬虫进阶一点点的网站。

这个博主很懒,经常拖更。

入门文章看这个 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

爬虫入门级别教程(小白水平).


前言

提示:这次的内容可能会稍微比上一篇文章难一丢丢,但是不涉及前端太深奥的东西,这些会在下一弹展示。


提示:以下是本篇文章正文内容。

一、游戏新闻中心

网址:http://news.17173.com

  • 第一步还是先看一看网页结构,找一找我们要爬取的数据在什么地方。
    在这里插入图片描述

  • 先按F12打开开发者模式 然后点击刷新网页的按钮
    在这里插入图片描述

  • 观察并找到是否有我们想要的数据,这里有三个包,如果好奇的话可以一个个点进去看。
    在这里插入图片描述

  • 一般想这种带有List的都是带有我们数据的。如果你经常看网站也会得到这样的结论。或者你可以看一下文件的后缀。这里有js和jsonp,js大家应该都熟悉、jsonp(JSON with Padding) 是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域获取资料。

  • 我们双击一下这个包
    在这里插入图片描述

  • 我们会发现这很有可能就是我们想要的数据,但是太杂乱了。
    在这里插入图片描述

  • 看到这大家可能觉得有点眼熟,这玩意跟JSON也太像了吧?我们把这个粘贴到JSON在线解析去。大家会发现好像有点不太对劲。我们先去掉这个括号前面的东西,删掉文末最后一个括号。
    在这里插入图片描述

  • 这样就正常了
    在这里插入图片描述

  • 但我们得到这个数据之后有两种办法来获取我们想要的东西。

    • 1、用代码将刚刚叙述的东西删除,然后转换成JSON的格式进行获取。但这个我尝试了很久很久很久。最终也没有成功。不过小伙伴们可以尝试一下~ (Python字符串转字典, 成功之后可以评论区留言~互相学习)

      Python字符串转字典.

    • 2、就是一点点切分了,找到我们想要的东西。

  • 我使用的是第二种方法,只好掏出正则这个神器了。怎么用呢?就是用正则匹配出标题和新闻的正文网址。经过观察我们就可以写出正则表达式。写正则偷懒的方法就是复制你要匹配的东西,把你要匹配的东西换成(.*?),这里pageUrl是必须的,title也是必须的。而括号里面是我需要的。它的意思是匹配任意。所以当你想匹配其他任意(但这些不是你所需要的)也可以使用它,只不过这次不要带上括号。

    .*?的含义.

# 用正则来匹配url和标题
com1 = re.compile(r'"pageUrl":"(.*?)"', re.S)  
com2 = re.compile(r'"title":"(.*?)"', re.S)

在这里插入图片描述

  • 我们再看看请求头
    在这里插入图片描述
  • 发现这里的参数确实有点多,我们先往下多刷出点一样的包来观察一下。
    在这里插入图片描述
    在这里插入图片描述
  • 发现只有"pageNo"和"_"这两个参数是改变的
  • pageNo大概猜测一下就是页码数。
  • 但这个"_"是什么鬼?我本来正在烧脑中但是发现不过也就是从43变成了44,那下一个包是不是45?
    在这里插入图片描述
  • 这印证了我的观点,也就是说你访问下一个包时这个参数是要比前一个参数大1的。
  • 在获得了新闻文本url后该怎么做呢?
  • 老规矩按F12,然后开始找我们要的东西
    在这里插入图片描述
  • 找到了。这里就可以采用之前的xpath进行爬取了。但是有许多个部分被包在了不同的div标签里面。这个时候只需要到上一层级去,并"获取下层级所有文本内容即可"
//text() : 获取所有的文本内容
  • 代码如下:
import requests
from lxml import etree
import pandas as pd
import re

if __name__ == '__main__':
    com1 = re.compile(r'"pageUrl":"(.*?)"', re.S)  # 用正则来匹配url和标题
    com2 = re.compile(r'"title":"(.*?)"', re.S)

    # 持久化存储用
    l_main = []

    # 网址
    url = "http://interface.17173.com/content/list.jsonp?"

    # 必要的参数
    params = {
        "callback": "jQuery1111044137195735135837_1625278587501",
        "categoryIds": "10019,10152,10161",
        "pageSize": "21",
        "pageNo": "1",
        "_": "16252785875",
    }

    count = 0

    headers = {
        "Referer": "http://news.17173.com/",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/89.0.4389.82 Safari/537.36 "
    }

    for j in range(2, 100):  # 循环爬取数据

        count += 1

        params['pageNo'] = str(j)  # 参数会改变

        if count < 10:  # 这里也是, 小于10的时候和大于了是不一样的
            params['_'] = params['_'] + '0' + str(count)
        else:
            params['_'] = params['_'] + str(count)

        res = requests.get(url=url, headers=headers, params=params)

        data = "".join(res.text.rstrip(")").split("(")[1:])  # 删去右侧的括号以及左侧不需要的部分
        data_list_all_ = "".join(data.split(":[")[1:])  # 删除左边不需要的部分
        data_list_all = data_list_all_.split("}")
        for i in data_list_all:
            if len(com1.findall(i)) == len(com2.findall(i)) and len(com1.findall(i)) != 0 and len(com2.findall(i)) != 0:
                news_url = com1.findall(i)[0]
                news_title = com2.findall(i)[0]
                news_res = requests.get(url=news_url, headers=headers)
                news_res.encoding = "UTF-8"  # 设置编码
                tree = etree.HTML(news_res.text)  # 用xpath进行查找
                string = tree.xpath('//div[@class="gb-final-pn-article"]/div[@class="gb-final-mod-article '
                                    'gb-final-mod-article-p2em"]//text()')

                string = "".join(string)
                string = string.replace("\r", "").replace("\n", "").replace("\t", "").replace(" ", "").strip()  # 清洗字符串
                print(string)

                l_group = [string, '游戏', news_title]
                l_main.append(l_group)

                news_res.close()

                print(j, "下载成功!")
    res.close()

    # 进行持久化存储
    df = pd.DataFrame(l_main, index=[i for i in range(len(l_main))], columns=['content', 'channelName', 'title'])
    df.to_csv("游戏新闻.csv")

二、房产要闻-和讯网

网址:http://house.hexun.com/list/

  • 同样的还是先看看网页结构
    在这里插入图片描述
  • 我认为可能是点击完成后再进行动态加载的
    在这里插入图片描述
  • 果不其然是这样的,而且数据的返回形式和第一个网页也是一样的
  • 来看看请求头
    在这里插入图片描述
  • 好像有点复杂,我们对照这下一个包看看。
    在这里插入图片描述
  • 这里的cp是表示第几张页面
  • 除了callback,其他参数并没有发生改变
  • 仔细观察可以发现hx_json后面的第一个数字应该表示的是页码,我们可以再点到第三页看看。
    在这里插入图片描述
  • 显而易见是这样的,而且中间有一段是相同的,但最后几位并不相同。
  • 这几位有可能经过了是经过加密处理而生成的,当然也有可能就是随机数。
  • 运行之后发现成功!说明并没有想象之中的复杂
  • 代码如下
import requests
from lxml import etree
import pandas as pd
import re

if __name__ == '__main__':
    com1 = re.compile(r'"entityurl":"(.*?)"', re.S)
    com2 = re.compile(r'"title":"(.*?)"', re.S)
    l_main = []
    url = "http://open.tool.hexun.com/MongodbNewsService/newsListPageByJson.jsp?"

    params = {
        "id": "100135470",
        "s": "50",
        "cp": "4",
        "priority": "0",
        "callback": "hx_json11625273727797"
    }

    headers = {
        "Referer": "http://house.hexun.com/",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/89.0.4389.82 Safari/537.36 "
    }

    # 拼接
    list_ = "hx_json11625273727797".split("1", 1)

    for j in range(1, 40):

        params['callback'] = str(j).join(list_)  # 修改访问参数

        res = requests.get(url=url, headers=headers, params=params)

        # 下面是进行数据的处理
        data = res.text.split("(")[1].split(")")[0].strip().replace("\\", "")

        data_list = data.split("[")

        data_list_all = data_list[1].split("{")

        for i in data_list_all:
            # 避免错误数据
            if len(com1.findall(i)) == len(com2.findall(i)) and len(com1.findall(i)) != 0 and len(com2.findall(i)) != 0:
                news_url = com1.findall(i)[0]
                news_title = com2.findall(i)[0]  # 正则表达式进行查找
                news_res = requests.get(url=news_url, headers=headers)
                news_res.encoding = "gb2312"  # 设置编码
                tree = etree.HTML(news_res.text)
                string_list = tree.xpath('//div[@class="art_context"]/div[@class="art_contextBox"]//text()')
                string = ",".join(string_list)
                string = string.replace("\r", "").replace("\n", "").replace("\t", "").replace(" ", "").strip()  # 数据处理
                l_group = [string, '房产', news_title]
                l_main.append(l_group)

                news_res.close()

                print(j, "下载成功!")
    res.close()

    # 持久化存储
    df = pd.DataFrame(l_main, index=[i for i in range(len(l_main))], columns=['content', 'channelName', 'title'])
    df.to_csv("房产新闻.csv")

三、梨视频

网址: https://www.pearvideo.com

  • 大致看上去有两种类型:一种是可直接播放,一种是不可直接播放。
  • 可直接播放的我们来找一找有没有视频地址。
    在这里插入图片描述
  • 如果找到了视频地址的话,就可以直接对视频地址发送请求。
# 因为图片和视频都是二进制的形式
requests.get(url=url).content
  • 但也有没有视频地址的情况
    在这里插入图片描述
  • 这个是没有视频地址的,但是有个传送门,其实也就相当于是视频地址了。我们点击它。发现跳到了这。
    在这里插入图片描述
  • 我们再寻找一下这个视频地址在哪。
    在这里插入图片描述
  • 这就和前面一样了,可以对这个地址发送请求,再用".content"方法
  • 整体流程也就清晰了,只不过要做一下url的拼接,小伙伴们去练练手吧~

总结

本文主要介绍了爬虫入门中可能会使用到的一点小方法和技巧。没有涉及过深的前端知识。下一弹会更带有一些深度的前端知识的网页的爬取。加油,小伙伴~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值