【Python_requests学习笔记(八)】基于requests模块 实现响应内容嵌入JS 进行url地址跳转 数据的爬取

基于requests模块构建免费代理IP池

前言

此篇文章中介绍基于requests模块,实现对在响应内容中嵌入JS,真实的url地址进行跳转后数据的爬取,并以爬取行政区划代码数据为例进行讲解。

正文

1、需求梳理

抓取民政部网站最新行政区划代码
一级页面:
在这里插入图片描述
二级页面:
在这里插入图片描述

2、爬虫思路

  1. 确认所抓数据在响应内容中是否存在
    一级页面抓取数据:
    在这里插入图片描述
    二级页面抓取数据:
    在这里插入图片描述

  2. 分析url地址规律
    一级页面的url地址:https://www.mca.gov.cn/article/sj/xzqh/2020/
    二级页面的url地址:https://www.mca.gov.cn/article/sj/xzqh/2020/2020/202101041104.html
    注意:获取二级页面的url地址时,因为网站加入了反爬机制,在响应内容中嵌入了JS,所以url地址会进行跳转,在一级页面中获取的url地址并不是真实的url地址
    在这里插入图片描述
    从上面的动图中可以看到:url地址从 https://www.mca.gov.cn//article/sj/xzqh/2020/202101/20210100031547.shtml 跳转成了 https://www.mca.gov.cn/article/sj/xzqh/2020/2020/202101041104.html
    那么应该如何获取二级页面真实的url地址呢?
    本文采用的方法是:在程序运行时打印二级页面的响应内容,在响应内容中Ctrl+F 寻找 url地址(https://www.mca.gov.cn/article/sj/xzqh/2020/2020/202101041104.html )
    在这里插入图片描述

  3. 写xpath表达式 & re正则表达式
    在这里插入图片描述

一级页面的xpath表达式://tr//@href
在这里插入图片描述
二级页面的re表达式:window.location.href="(.*?)

  1. 编写程序框架、完善程序
    详情见3、程序实现

3、程序实现

  1. 初始化函数
    def __init__(self):
        self.url = 'https://www.mca.gov.cn/article/sj/xzqh/2020/'  # url地址
  1. 功能函数1:获取html
    def get_html(self, url):
        """
        function:  功能函数1:获取html
              in:  url:url地址
             out:  html:返回响应内容
          return:  html:返回响应内容
          others:  Func1:Get HTML
        """
        headers = {'User-Agent': UserAgent().random}  # 构建随机请求头
        html = requests.get(url=url, headers=headers).text  # get方法获取响应内容
        return html
  1. 功能函数2:xpath解析提取数据
    def xpath_func(self, html, xpath_bds):
        """
        function:  功能函数2:xpath解析提取数据
              in:  html:响应内容
                   xpath_bds:xpath表达式
             out:  r_list:返回匹配内容
          return:  r_list:返回匹配内容
          others:  
        """
        p = etree.HTML(html)  # 创建解析对象
        r_list = p.xpath(xpath_bds)  # 解析对象调用xpath表达式
        return r_list  # 返回匹配内容
  1. 逻辑函数
    def parse_html(self):
        """
        function:  逻辑函数
                   1、向主页发请求,提取最新月份的链接
                   2、向最新月份的链接发请求,提取数据
              in:  None
             out:  None
          return:  int >0 ok, <0 some wrong 
          others:  Logic Func
        """
        one_html = self.get_html(url=self.url)  # 获取html内容
        one_xpath = '//tr//@href'  # 定义xpath表达式
        href_list = self.xpath_func(html=one_html, xpath_bds=one_xpath)  # xpath解析提取数据
        if href_list:  # 判断是否存在
            one_url = 'https://www.mca.gov.cn' + href_list[0]  # 拼接返回列表的第一项
            self.detail_page(one_url)  # 调用 详情页获取具体数据函数
        else:
            print("提取最新链接失败!")
  1. 详情页获取具体数据
    def detail_page(self, one_url):
        """
        function:  详情页获取具体数据
              in:  one_url:一级页面的url地址
             out:  None
          return:  None
          others:  The Details Page Gets Data
        """
        # 在响应内容中嵌入JS,进行了url地址的跳转

        two_html = self.get_html(one_url)  # 传入详情页的url地址
        true_url = self.get_true_url(two_html)  # 从响应内容中提取真实返回数据的链接

        true_html = self.get_html(true_url)  # 开始从真实链接中提取数据
        two_xpath = "//tr[@height='19']"  # 写xpath表达式
        tr_list = self.xpath_func(html=true_html, xpath_bds=two_xpath)
        item = {}  # 定义一个空字典
        for tr in tr_list:
            item["name"] = tr.xpath('./td[3]/text()')[0].strip()
            item["code"] = tr.xpath('./td[2]/text()|./td[2]/span/text()')[0].strip()
            print(item)
  1. 从响应内容中提取真实返回数据的url地址
    def get_true_url(self, two_html):
        """
        function:  从响应内容中提取真实返回数据的url地址
              in:  two_html:二级页面的响应内容
             out:  true_url[0]:真实的url地址
          return:  true_url[0]:真实的url地址
          others:  From Html Get True Url
        """
        regex = 'window.location.href="(.*?)"'  # 正则表达式
        pattern = re.compile(regex, re.S)  # 创建正则表达式编译对象
        true_url = pattern.findall(two_html)  # 使用findall方法
        return true_url[0]  # 返回真实的url地址
  1. 程序入口函数
    def run(self):
        """
        function:  程序入口函数
              in:  None
             out:  None
          return:  None
          others:  Program Entry Func
        """
        self.parse_html()  # 调用逻辑函数

4、完整代码

import re
import requests
from lxml import etree
from fake_useragent import UserAgent

class MinzhengSpider:
    """
    抓取民政部网站最新行政区划代码
    """

    def __init__(self):
        self.url = 'https://www.mca.gov.cn/article/sj/xzqh/2020/'  # url地址

    def get_html(self, url):
        """
        function:  功能函数1:获取html
              in:  url:url地址
             out:  html:返回响应内容
          return:  html:返回响应内容
          others:  Func1:Get HTML
        """
        headers = {'User-Agent': UserAgent().random}  # 构建随机请求头
        html = requests.get(url=url, headers=headers).text  # get方法获取响应内容
        return html

    def xpath_func(self, html, xpath_bds):
        """
        function:  功能函数2:xpath解析提取数据
              in:  html:响应内容
                   xpath_bds:xpath表达式
             out:  r_list:返回匹配内容
          return:  r_list:返回匹配内容
          others:  
        """
        p = etree.HTML(html)  # 创建解析对象
        r_list = p.xpath(xpath_bds)  # 解析对象调用xpath表达式
        return r_list  # 返回匹配内容

    def parse_html(self):
        """
        function:  逻辑函数
                   1、向主页发请求,提取最新月份的链接
                   2、向最新月份的链接发请求,提取数据
              in:  None
             out:  None
          return:  int >0 ok, <0 some wrong 
          others:  Logic Func
        """
        one_html = self.get_html(url=self.url)  # 获取html内容
        one_xpath = '//tr//@href'  # 定义xpath表达式
        href_list = self.xpath_func(html=one_html, xpath_bds=one_xpath)  # xpath解析提取数据
        if href_list:  # 判断是否存在
            one_url = 'https://www.mca.gov.cn' + href_list[0]  # 拼接返回列表的第一项
            self.detail_page(one_url)  # 调用 详情页获取具体数据函数
        else:
            print("提取最新链接失败!")

    def detail_page(self, one_url):
        """
        function:  详情页获取具体数据
              in:  one_url:一级页面的url地址
             out:  None
          return:  None
          others:  The Details Page Gets Data
        """
        # 在响应内容中嵌入JS,进行了url地址的跳转
        two_html = self.get_html(one_url)  # 传入详情页的url地址
        true_url = self.get_true_url(two_html)  # 从响应内容中提取真实返回数据的链接

        true_html = self.get_html(true_url)  # 开始从真实链接中提取数据
        two_xpath = "//tr[@height='19']"  # 写xpath表达式
        tr_list = self.xpath_func(html=true_html, xpath_bds=two_xpath)
        item = {}  # 定义一个空字典
        for tr in tr_list:
            item["name"] = tr.xpath('./td[3]/text()')[0].strip()
            item["code"] = tr.xpath('./td[2]/text()|./td[2]/span/text()')[0].strip()
            print(item)

    def get_true_url(self, two_html):
        """
        function:  从响应内容中提取真实返回数据的url地址
              in:  two_html:二级页面的响应内容
             out:  true_url[0]:真实的url地址
          return:  true_url[0]:真实的url地址
          others:  From Html Get True Url
        """
        regex = 'window.location.href="(.*?)"'  # 正则表达式
        pattern = re.compile(regex, re.S)  # 创建正则表达式编译对象
        true_url = pattern.findall(two_html)  # 使用findall方法
        return true_url[0]  # 返回真实的url地址

    def run(self):
        """
        function:  程序入口函数
              in:  None
             out:  None
          return:  None
          others:  Program Entry Func
        """
        self.parse_html()  # 调用逻辑函数


if __name__ == '__main__':
    spider = MinzhengSpider()
    spider.run()

5、实现效果

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

禾戊之昂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值