网络爬虫之数据提取方式

image.png

**

网页

image.png

正则表达式

正则表达式(Regular Expression):使用一种表达式的方法对字符串进行匹配的语法规则。

常用的元字符
.匹配除换行以外的任意字符
\w | \W匹配字母数字或下划线 | 匹配非字母数字或下划线
\s | \S匹配任意空白符 | 匹配非空白符
\d | \D匹配数字 | 匹配非数字
\n匹配一个换行符
\t匹配一个制表符
^匹配字符串的开始
$匹配字符串的结尾
a | b匹配字符a或b
()匹配包括内的表达式
[........]匹配字符串组的字符
[^......]匹配除字符串组的字符
量词
*重复零次或更多
+重复一次或更多
重复零次或一次
{n}重复n次
{n,}重复n次或更多
{n,m}重复n到m次
.*贪婪匹配,尽可能多的去匹配
.*?非贪婪匹配,尽可能少的匹配

Python内置模块re。

re修饰符
修饰符描述
re.l使匹配对大小写不敏感
re.L对本地化识别匹配
re.M多行匹配,影响^和$
re.S使匹配包括行内所有的字符
re.U根据 Unicode 字符集解析字符。这个标志影响 \w、\W、\b 和 \B
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解
re常用方法
re.findall查找返回所有,返回list
re.finditer查找返回所有,返回一个迭代器
re.search返回第一个结果
re.match从第一个字符串开始匹配,没匹配到,返回None

案例,获取2021年第四季度全国星级饭店统计调查报告发布时间。

image.png

发布时间的数据在<script></script>中,可以利用正则表达式获取。

# -*- encoding:utf-8 -*-

​

import re
import requests
​
​
HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
    "referer": "https://sjfw.mct.gov.cn/site/dataservice/details?id=27170"
}
​
# 获取网页源代码
def get_source_code():
    url = "https://sjfw.mct.gov.cn/site/dataservice/details?id=27170"
    res = requests.request("GET",url=url, headers=HEADERS)
    res.encoding = "utf-8"
    return res.text
​
# 处理数据
def data_process(code):    
    deal = re.compile(r'<script>window.__NUXT__=.*publish_time:"(.*)",picture',re.S)
    publish_time = deal.findall(code)[0]
    print(publish_time)
​
if __name__ == '__main__':
    code = get_source_code()
    data_process(code)

Xpath

 安装第三方模块lxml

 pip install lxml

  导包 from lxml import etree

  实例化 parse = etree.HTML(html)

选取节点
/从根结点获取
//从匹配选择当前的节点选择文档中的节点
.选取当前节点
..选取当前节点的父节点
@选择属性
选取未知节点
*匹配任何元素节点
@*匹配任何属性节点
node()匹配任何类型节点
最左侧 /表示必须树的根标签(HTML)开始定位
最左侧 //可以从任意位置进行标签的相对定位
非最左侧 /表示一个层级
非最左侧 //表示多个层级

常用方法

获取属性内容

  • 获取href
  • 获取title

<div><ul><li><a><li>....<ul></div>

//div/ul/li/a/@href

//div/ul/li/a/@title

获取文本内容

//div/ul/li/a/text()

案例 获取故宫壁纸,通过Xpath获取图片标题和src

image.png

# -*- encoding:utf-8 -*-

​
​
import requests
from lxml import etree
​
​
HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
    "referer": "https://www.dpm.org.cn/lights/royal.html"
}
​
# 获取网页源代码
def get_source_code():
    url = "https://www.dpm.org.cn/lights/royal.html"
    res = requests.request("GET",url=url, headers=HEADERS)
    res.encoding = "utf-8"
    return res.text
​
def data_process(code):
    # 实例化xpath方法
    parse = etree.HTML(code)
    dict_pic = {}
    # 定位最外层div标签
    result = parse.xpath('//div[@class="pic"]')
    for pic in result[0]:
        for i in range(len(result)):
            title = pic.xpath("//a/img/@title")[i]
            url = pic.xpath("//a/img/@src")[i]
            dict_pic[title] = url
    return dict_pic
​
​
if __name__ == '__main__':
    code = get_source_code()
    print(data_process(code))

BeautifulSoup

安装第三方模块 pip install bs4

导包 from bs4 import BeautifulSoup

实例化 page = BeautifulSoup(html, "html.parser")

常用的定位方式

标签定位

find()、find_all()

属性定位

find("标签名",attrs={"属性名":"属性"})

find_all("标签名",attrs={"属性名":"属性"})

选择器定位

select(css选择器)

  • id选择器 #
  • class选择器 .
  • 层级选择器 >表示层级 空格表示多层级

提取方式

提取标签内容

tag.string 只可以提取到标签中直系的文本内容

tag.text 可以提取到标签中所有的文本内容

提取标签属性

tag["attrName"]

案例:获取必应壁纸,通过bs4-属性定位获取图片url和title

image.png

# -*- encoding:utf-8 -*-

​
​
import requests
from bs4 import BeautifulSoup


HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
    "referer": "https://bing.ee123.net/"
}


# 获取网页源代码
def get_resource_code():
    url = "https://bing.ee123.net/"
    res = requests.request("GET", url=url, headers=HEADERS,verify=False)
    return res.text

# 处理数据
def data_process(code):
    page = BeautifulSoup(code, "html.parser")
    result = page.find_all("div", attrs={"id": "view_photoList"})
    img_dict = {}
    for i in result:
        # 获取url
        img = i.find('img')
        url = img["src"]
        # 获取图片title
        title_info = i.find('h2')
        title = title_info.text.split("(")[0]
        img_dict[title] = url
    return img_dict


if __name__ == '__main__':
    code = get_resource_code()
    print(data_process(code))

PyQuery

安装第三方库 pip install pyquery

导包 from pyquery as PyQuery as pq

实例化 doc = pq(html)

常用的定位方式

css选择器定位

层级样式

  • id选择器 #
  • class选择器 .
  • 层级选择器 >表示层级 空格表示多层级

提取方式

提取标签内容

tag.text() 可以提取到标签中所有的文本内容

提取标签属性

tag.attr("标签名")

案例:车型价位获取,通过Pyquery-css样式选择器方式定位。

image.png

# -*- encoding:utf-8 -*-



import requests
from pyquery import PyQuery as pq

HEADERS = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"}
INDEX = "https://car.yiche.com/"



def parse_index(url):
    """
    处理首页
    @param url: 首页url
    @return: 返回源代码
    """
    res = requests.request("GET", url=url, headers=HEADERS)
    res.encoding = "utf-8"
    return res.text


def car_model(html):
    """
    各类车型处理
    @param html:首页源代码
    @return: 车型:子页面
    """
    doc = pq(html)
    # 提取所有品牌链接
    brands = doc('.brand-list-item .item-brand')
    # 创建一个空字典来存储提取的车名和URL
    car_dict = {}
    # 遍历每个品牌,提取车名和URL
    for brand in brands.items():
        car_name = brand.attr('data-name')
        car_url = brand.parent().attr('href')
        car_dict[car_name] = "https://car.yiche.com"+ car_url

    return car_dict


def process_car(html):
    """
    车型名称和价格获取
    @param html:
    @return: 车型:价位
    """
    doc = pq(html)
    brand = doc(".search-result-list-item")
    car_dict = {}
    for car in brand.items():
        car_name = car(".cx-name").text()
        car_price = car(".cx-price").text()
        car_dict[car_name] = car_price
    return car_dict


if __name__ == '__main__':
    car_info = parse_index(INDEX)
    car_dict = car_model(car_info)
    tip = """
    请输入要获取车型最新价格
    如 奥迪
    """
    # 输入要查询的车型名
    car_name = input(tip)
    car_url = car_dict[car_name]
    # 处理该类车型,进入车型页面
    car_code = parse_index(car_url)
    # 处理车型页面,获取具体的车型和价格
    brand_car = process_car(car_code)
    f = open(f"{car_name}.text", 'w', encoding="utf-8")
    if  bool(brand_car):
        for k, v in brand_car.items():
            f.write(f"{k}  -价格区间 {v}\n")
        print("下载成功,见文件内容")
    else:
        print("未找到合适的车型")
    f.close()

接口

image.png

未加密

API接口

通过抓包,获取请求方法、url,请求参数、请求头,发起请求即可获取接口数据。通过json.loads()方法将字符串转为字典,通过键值对获取想要的数据。 案例:移动观象台-获取应用排行top10的应用名称、所属公司、活跃度。

image.png

# -*- encoding:utf-8 -*-

​
​
import requests
import json
​
HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
    "referer": "http://mi.talkingdata.com/app-rank.html"
}
​
​
def get_app_data():
    url = "http://mi.talkingdata.com/rank/active.json?date=2022-11-01&typeId=0&dateType=m&rankingStart=0&rankingSize=30"
    res = requests.request("GET",url=url, headers=HEADERS)
    return res.text
​
​
def get_top_10(code):
    data = json.loads(code)
    data_list = []
    for i in range(10):
        app_info = []
        # app名称、所属公司、app活跃度
        app_name = data[i]["appName"]
        company = data[i]["company"]
        activeRate = data[i]["activeRate"]
        app_info.extend([app_name,company,activeRate])
        data_list.append(app_info)
    return data_list
​
​
if __name__ == '__main__':
    code = get_app_data()
    print(get_top_10(code))

加密

API接口-加密

        JavaScript逆向找到加密解密方式。之后的步骤如同API接口。

image.png

提取数据方法总结

  • Xpath

        适用于要获取的信息在某个标签下,且各标签层次明显,通过路径找到位置,for循环遍历即可

  • Bs4

        适用于要获取的信息比较分散,且通过选择器可以定位(class唯一、id唯一)

  • PyQuery

        适用于要获取的信息比较分散,且通过选择器可以定位(class唯一、id唯一)

  • 正则

        通过(.*?)就可以处理元素失效或者定位少量信息 不适用网页代码有很多其它符号,定位失效 数据在JavaScript代码中;

  • 接口返回数据

        对于接口没有进行加密,通过requests构造请求即可获取数据 关注点在请求头中的参数(UA、防盗链等)

  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值