Python爬虫--2

1、数据解析

数据解析有三种方式:

        (1)正则表达式;

        (2)bs4;

        (3)xpath(学习重点,通用性强)。

数据解析原理概述:

        (1)解析的局部文本内容都会在标签之间或者标签对应的属性中进行存储;

        (2)进行指定标签的定位;

        (3)标签或者标签对应的属性中存储的数据值进行提取;

聚焦爬虫:

        指定url;

        发起请求;

        获得响应数据;

        数据解析;

        持久化存储。

1.1、正则表达式

爬虫中常用的正则表达式:

单字符:

.

除换行以外所有字符

[]

【aoe】【a-w】匹配集合中任意一个字符

\d

数字【0-9】

\D

非数字

\w

数字、字母、下划线、中文

\W

非\w

\s

所有的空白字符包,包括空格、制表符、换页符等;等价于【\f、\n、\r,\t,\v】

\S

非空白

数量修饰:

*

任意多次,>=0

+

至少一,>=1

可有可无,0或者1次

{m}

固定m次,hello{3,}

{m,}

至少m次

{m,n}

m-n次

边界:

$

以某某结尾

^

一某某开头

分组:

(ab)

贪婪模式:

        .*

非贪婪(惰性)模式:

        .*?

忽略大小写:

        re.I

多行匹配:

        re.M

单行匹配:

        re.S

res.sub(正则表达式,替换内容,字符串)

示例:

(1)爬取百度图片上一张图片

# -*-coding = utf-8-*-
# 数据解析--爬取一张图片。
import requests
import json

if __name__ == '__main__' :
    request_header = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74'
    }

    url = "http://img.daimg.com/uploads/allimg/210916/3-210916110348.jpg"

    # content返回的是二进制形式的图片数据
    # text(字符串类型的数据);content(二进制类型的数据);json()(对象类型的数据)
    img_data = requests.get(url=url).content

    with open("./temp/data-test-1-图片.jpg", 'wb') as fp :
        fp.write(img_data)

    print('保存成功!')

(2)爬取百度图片上多张图片

爬取内容如下:

(2)分析如下:

根据网页的elements的信息找到其中一张图片对应的网页代码。过程如下:

Python爬虫--2_第1张图片

Python爬虫--2_第2张图片

Python爬虫--2_第3张图片

Python爬虫--2_第4张图片

Python爬虫--2_第5张图片

最后一个红框内的内容就是我们最终想要得到的图片的地址信息。该图片的地址信息为:

https://img2.baidu.com/it/u=1339760433,3371235111&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800

# -*-coding = utf-8-*-
# 数据解析--爬取百度壁纸上的图片。
import requests
import re

if __name__ == '__main__' :
    # 指定url,百度壁纸的url
    url = "https://image.baidu.com/search/index?ct=201326592&z=&tn=baiduimage&ipn=r&word=%E5%9B%BE%E7%89%87%E5%A3%81%E7%BA%B8&pn=&spn=&istype=2&ie=utf-8&oe=utf-8&cl=2&lm=-1&st=-1&fr=&fmq=1694354439648_R&ic=&se=&sme=&width=&height=&face=0&hd=&latest=©right=&cs=&os=&objurl=&di=&gsm=1e&dyTabStr=MTEsMCwxLDMsNiw0LDUsMiw4LDcsOQ%3D%3D"

    # UA伪装
    form_header = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74'
    }

    # 设置参数
    # "pn": "2"   【从第几个图片开始爬取】
    # "rn": "30"  【每次爬取30个图片】
    param = {
                "tn": "resulttagjson",
                "logid": "8997413208058539128",
                "ie": "utf-8",
                "fr": "",
                "word": "图片壁纸",
                "ipn": "r",
                "fm": "index",
                "pos": "history",
                "queryWord": "图片壁纸",
                "cl": "2",
                "lm": "-1",
                "oe": "utf-8",
                "adpicid": "",
                "st": "-1",
                "z": "",
                "ic": "",
                "hd": "",
                "latest": "",
                "copyright": "",
                "s": "",
                "se": "",
                "tab": "",
                "width": "",
                "height": "",
                "face": "0",
                "istype": "2",
                "qc": "",
                "nc": "1",
                "expermode": "",
                "nojc": "",
                "isAsync": "true",
                "pn": "2",
                "rn": "30",
                "itg": "1",
                "gsm": oct(10),
                "1694356611366": ""
    }

    # 执行一个get操作,得到网页源代码
    res = requests.get(url, headers=form_header, params = param).text
    print("打印网页源代码:", res)

    # 正则表达式【在源代码中过滤关键性的信息】
    # 通过查看res的内容,发现每一个图片网址的前面都是对应着thumbURL,通过匹配查找thumbURL,可以快读定位到图片的地址。
    image_urls = re.findall('"thumbURL":"(.*?)",', res)

    # 通过得到的所有图片的网址,下载保存图片
    i = 0
    for image_url in image_urls:
        i += 1  # 用数字作为图片的名称
        print("图片的url:", image_url)

        # 图片名称
        image_name = "tupian-" + str(i) + ".jpg"
        print("图片的名字:", image_name)

        # 保存
        image = requests.get(image_url).content
        with open('./temp/data-test-2/%s' % image_name, 'wb') as file:
            file.write(image)

    print("保存成功!")

上述代码有一些问题,暂时没有更改,希望有懂得同学给一些意见。

1.2、bs4

暂不做解释。

1.3、xpath

最常见且最便捷高效的一种解析方式。

xpath解析原理:

        1、需要实例化一个etree的对象,且需要将被解析的页面源码加载到该对象中。

        2、通过调用etree对象中的xpath方法结合xpath表达式,实现标签的定位和内容的捕获。

环境安装:

        1、etree安装

        2、安装lxml

如何实例化etree对象:【form lxml import etree】

        1、将本地的html文档中的源码数据加载到etree对象中。调用etree.parse(filePath)方法。

        2、可以将从互联网上获取的页面源码数据加载到该对象中。调用etree.HTML(“page_text”)。

        3、xpath(“xpath表达式”)。

本地的一个html文档如下:




    
    Title---+++


    
  • 法治的细节
  • 纸质书
  • 30元
  • 罗翔
  • 李世民
  • 朱元璋
  • 朱棣
  • xpath表达式:

            “/”:表示的是从根节点开始定位,表示的是一个层级。

            “//”:表示的是可以从任意位置开始定位,表示的是多个层级。

            属性定位:“//target[@attrName=‘attrValue’]”。

            索引定位:“//target[@attrName=‘attrValue’]/target-1[index-value]”。index-value是从1开始的。

            取文本:“//target[@attrName=‘attrValue’]/target-1[index-value]/text()”。

            取属性:“/@attrName

    # -*-coding = utf-8-*-
    # 数据解析--xpath练习。
    import requests
    from lxml import etree
    
    if __name__ == '__main__' :
        # test.html是一个本地的网页文件, 实例化好了一个etree对象,将test.html源码加载到了tree中。
        tree = etree.parse('temp/test.html')
        print("-------------------------------------------------------------")
    
        # 返回的是一个 element 类型的列表;列表对应着title中的内容。
        r = tree.xpath("/html/head/title")
        print("r : ", r)
        print("-------------------------------------------------------------")
    
        # 返回的是一个 element 类型的列表;列表对应着div中的内容。
        # 因为test.html中有3个div,所以返回值列表中有3个元素
        r = tree.xpath("/html/body/div")
        print("r : ", r)
        r = tree.xpath("//div")
        print("r : ", r)
        print("-------------------------------------------------------------")
    
        # 返回的是一个 element 类型的列表;列表对应着div中的内容。
        # 属性定位
        r = tree.xpath("//div[@class='ming']")
        print("r : ", r)
        print("-------------------------------------------------------------")
    
        # 返回的是一个 element 类型的列表;列表对应着div中的内容。
        # 索引定位
        r = tree.xpath("//div[@class='song']/li[2]")
        print("r : ", r)
        print("-------------------------------------------------------------")
    
        # 返回的是一个 element 类型的列表;列表对应着div中的内容。
        # 取文本
        r = tree.xpath("//div[@class='song']/li[2]/text()")
        print("r : ", r)
        print("-------------------------------------------------------------")
    
        # 返回的是一个 element 类型的列表;列表对应着div中的内容。
        # 取属性
        r = tree.xpath("//div[@class='song']/li[2]/@id")
        print("r : ", r)
        print("-------------------------------------------------------------")
    

    结果为:

    -------------------------------------------------------------
    r :  []
    -------------------------------------------------------------
    r :  [, , ]
    r :  [, , ]
    -------------------------------------------------------------
    r :  []
    -------------------------------------------------------------
    r :  []
    -------------------------------------------------------------
    r :  ['纸质书']
    -------------------------------------------------------------
    r :  ['model']
    -------------------------------------------------------------
    
    
    

    2、示例

    2.1、爬取58同城二手房上的房源标题信息

    分析网页源码,找到对应的标题信息的源码

    Python爬虫--2_第6张图片

    Python爬虫--2_第7张图片

    # -*-coding = utf-8-*-
    # 数据解析--xpath--爬取58同城二手房的标题信息。
    import requests
    from lxml import etree
    
    if __name__ == '__main__' :
        # UA伪装
        header = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
        }
        url = "https://bj.58.com/ershoufang/"
    
        # 爬取页面源码数据
        page_text = requests.get(url, headers=header).text
    
        # 数据解析
        tree = etree.HTML(page_text)
        house_list = tree.xpath('//div[@class="property"]/a')
        #print(len(house_list))
    
        for lst in house_list :
            title = lst.xpath('./div[2]/div/div/h3/text()')[0]
            print(title)
    
    
    

    结果为:

    双井 急售2居 首付167w 全屋采光 开阔无遮挡 看房随时
    (业主跟我买的房)急售!周期马 到!钥匙在手!随时看
    业主急售房源!  东向两居室!高层看绿化 看好即谈!看房预约
    (优惠50W)东南三环,双地铁,低密洋房,南北通透,精装修
    性价比超高     两居 临河社区 靠近地铁 配套齐全
    双井百环家园东向大两居 随时看房业主诚意 满五年可配合
    急售可大聊,集中供暖,采光好,稳定签,断桥铝窗子
    北三环内 1995年 20平米客厅 本楼马 翻新 精装修
    宾客严选总价低 珠江帝景B区高层两居 看国贸朝阳双井合生汇
    10号线潘家园站 建业苑小区 1996年楼龄 精装修两居室
    买房收费0.1 南三环马家堡正规三居带电梯 满五V一 近地铁
      两居室 急售 满五年 随时可看 低于市场价
    [总监推荐] 双卧朝南 南北通透精装两居室 满五  
    草桥欣园三区2室1厅 普装
    板楼 集中供暖 南北通透 精装修   清晰 明厨明卫
    买房0.1 平安承保,地铁双线角门西,瑞丽江畔,两居,有钥匙
    季景沁园一居室满五年一套住房
    劲松 磨房北里 户型方正,全明格局 采光好 车位充足
    收费0.1交易有保单 海淀区电梯高楼层 视野好价格有惊喜
    三环新农村6号院南北通透两居!中间位置!价格合理看房方便!
    交易有保单 安心购 必看好房 城市涧2室1厅
    万象新天四区 正南向 采光好 精装修 满五年1套
    朝阳东四环,地铁17号线十八里店,朝央和煦,金隅昆泰云筑
    急降价60W!双井~富力城 13年楼盘,南北通透2居室
    亦庄东区 南北通透 集中供暖 正规商品房 交通便利 高楼层
    南北通透 居住密度低 刚需两居 高楼层采光充足 诚心出售
    速来围观 全南两居室 采光无遮挡 看房方便
    洋房两居!三面采光!降级急售!看房方便!
    小区户型方正满五年商品房
    百变户型三居 次顶层 诚意出售 可聊 海淀西北部
    三环里 百环家园 大户型两室两厅两卫 西向 精装修 高楼层
    业主急售 东三环 百环家园 集中供暖 精装可拎包入住 带电梯
    广渠南水关胡同小区 出行方便 满五   医疗配套成熟 临地铁
    常营保利嘉园 塔楼南北通透两居室
    主打两居室户型紧邻中央美苑宜家家居
    朝青 兴隆家园 南北通透 自住两室 满五   诚意卖 随时看
    中信新城东区 南北通透三居室 装修好
    四环边,地铁旁,东西通透,一梯两户带电梯
    北京新天地五期 2室2厅 全南向 中高楼层 精装修 满五年1
    崇文门总监推荐小两居  国瑞城   两居 方便看
    海淀嘉郡94.73平4   3室1厅1卫
    国贤府一起看!找我一定有额外优惠 !户型好 单价低
    望京四环边,业主降价急售,客厅卧室朝南,拎包入住!
    北街家园一区 客厅阳台 3室1厅 电梯房 一梯两户出行方便
    急售 百环家园 商品房 2室 1厅 95.91平米
    朝阳公园 近地铁 板楼 交通便捷 精装可拎包入住 南北通透
    东三环甄选好房,中位置中楼层,视野采光好,装修保养好,诚意
    1室1厅,满5年1套,三环富力城,8k国贸一站地
    环保嘉苑 满五年 高楼层 北清路 环保园
    首付200多万 12年品质社区 业主就想年前卖掉!随时看房
    北京城建海梓府 次小区新   清晰   的楼层 周边配套齐全
    急售老业主房源 保利罗兰香谷 三居做四居 南北通透 价格可谈
    新华街四里65.6平    2室2厅1卫
    永定门 富莱茵花园298W 2居东西 12层 法拍房
    急售  保利紫荆精装南北通透三居,看房随时 价格低
    大钟寺133号院两室一厅 满五   中间楼层 诚意出售
    东四环 四惠地铁一号线 商品房 南北通透板楼 满五年一套
    免收鲁谷路74号院 3室1厅 76.81平
    全网低价 南北双通透 原始地暖     
    双井家乐福九龙花园 后排不临街 安静 户型方正 精装修两居室
    (优惠50W)地铁五十米,望京精装现房,百米楼间距。
        ~    东坝金隅景和园七区 南北全明三居近地铁
    德顺园 环境好 双卫 房龄新 配套齐全 超低密度
    婚房装修 南  两居 宽阔客厅 高楼层 价格可谈 (  )
    急急急!!价格低 时代国际 南北两居 双井地铁站
    双卫两居,层高3.1米,满五年1套,付首300W,万科物业
    交易有保单 安心购 无遮挡,有钥匙随时看可大聊
    三环新城南北通透两居!精装修近地铁!高楼层彩光视野好!
    北苑聚焦(看房找我)世华泊郡(小区专家)精装两居(价可谈)
    南三环赵公口彩虹城四区满五年 商品房 全南向
    0.75 双地铁 园博嘉园东区 南北通透 两居室 前后无遮挡
    都会华庭 两居室 无遮挡 园区性价比高 二次装修 观景  
    紫薇天悦 08年次新社区 近关庄地铁站 房可看 亚运村
    (交易费0.5)无电梯低楼层 满五   价格可谈 急售
    东南北三面采光,精装修两居室,近地铁,中楼层,采光好!
    

    2.2、4K图片解析下载

    分析网页

    # -*-coding = utf-8-*-
    # 数据解析--xpath--爬取4K图片解析保存。
    # 网址为:https://pic.netbian.com/
    import requests
    from lxml import etree
    
    if __name__ == '__main__' :
        # UA伪装
        header = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
        }
        url = "https://pic.netbian.com/4kyouxi/"
    
        # 爬取页面源码数据
        response = requests.get(url, headers=header)
        #response.encoding = "utf-8"  # 设置编码格式
        page_text = response.text
    
        # 数据解析
        tree = etree.HTML(page_text)
        youxi_list = tree.xpath('//div[@class="slist"]/ul/li')
        #print(len(youxi_list))
    
        for lst in youxi_list :
            img_url = 'https://pic.netbian.com/' + lst.xpath('./a/img/@src')[0]
            img_name = lst.xpath('./a/img/@alt')[0] + '.jpg'
            img_name = img_name.encode('iso-8859-1').decode('gbk') # 通用处理中文乱码的解决
            print(img_url, img_name)
    
            resp = requests.get(img_url, headers=header).content
            f = open("./temp/data-test-6/{}".format(img_name), 'wb')
            f.write(resp)
    

    结果为:

    https://pic.netbian.com//uploads/allimg/240113/005103-17050782630110.jpg 英雄联盟 LOL 预知之眼 亚索8K游戏壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240112/184624-1705056384878d.jpg 2024年元旦《梦幻西游》电脑4K壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240112/184247-17050561673891.jpg 《梦幻西游》九黎突破 4k壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240111/011853-1704907133454c.jpg 三国之志4古风美女4k壁纸图片.jpg
    https://pic.netbian.com//uploads/allimg/231231/162254-17040109743be1.jpg 艾琳 觅芳踪 海报原画 王者荣耀 艾琳觅芳踪新皮肤 云梦有灵4K高清壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240109/232709-17048140290838.jpg 以闪亮之名 美少女 4k游戏壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240109/231746-1704813466393f.jpg 《赛博朋克2077》4k游戏壁纸图片.jpg
    https://pic.netbian.com//uploads/allimg/231231/164726-1704012446a57f.jpg Cyberpunk 2077 2024 赛博朋克5k壁纸.jpg
    https://pic.netbian.com//uploads/allimg/231219/200129-17029872895dbd.jpg 解限机 Mecha Break 4k游戏壁纸.jpg
    https://pic.netbian.com//uploads/allimg/231215/115152-17026123124601.jpg 金克丝 英雄联盟LOL 4k游戏壁纸.jpg
    https://pic.netbian.com//uploads/allimg/231213/233900-1702481940bb59.jpg 完美世界 清漪 同人美女4k电脑壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240107/204914-17046317542384.jpg 鬼谷子天穹祈灯皮肤超清无水印 王者荣耀4k壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240105/002348-17043854288f80.jpg 永劫无间 新英雄 魏轻4k高清壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240108/010652-1704647212c6dd.jpg 绝地求生pubg 2024 新年 4k游戏壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240108/002114-17046444749992.jpg 战双帕弥什赛琳娜4k壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240108/001833-170464431356bd.jpg 战双帕弥什露娜4k壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240108/000340-17046434207a93.jpg 战双帕弥什露西亚4k壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240108/000151-170464331103ea.jpg 战双帕弥什七实4k壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240107/235753-17046430732c7f.jpg 战双帕弥什蒲牢4k壁纸.jpg
    https://pic.netbian.com//uploads/allimg/240107/235033-17046426334ceb.jpg 战双帕弥什卡列尼娜4k壁纸.jpg
    

    2.3、全国城市名称爬取

    Python爬虫--2_第8张图片

    Python爬虫--2_第9张图片

    # -*-coding = utf-8-*-
    # 数据解析--xpath--爬取全国城市名称。
    # 网址为:https://pic.netbian.com/
    import requests
    from lxml import etree
    
    if __name__ == '__main__' :
        # UA伪装
        header = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
        }
        url = "https://www.aqistudy.cn/historydata/"
    
        # 爬取页面源码数据
        page_text = requests.get(url, headers=header).text
    
        # 数据解析
        tree = etree.HTML(page_text)
    
        print("---------------------- 热门城市数据 ----------------------")
        hot_city_list = tree.xpath('//div[@class="bottom"]/ul/li')
    
        for lst in hot_city_list :
            hot_city_name = lst.xpath('./a/text()')[0]
            print(hot_city_name)
    
        print("---------------------- 全部城市数据 ----------------------")
        all_city_list = tree.xpath('//div[@class="bottom"]/ul/div[2]/li')
    
        for lst in all_city_list :
            city_name = lst.xpath('./a/text()')[0]
            print(city_name)
    
    

    结果:

    ---------------------- 热门城市数据 ----------------------
    北京
    上海
    广州
    深圳
    杭州
    天津
    成都
    南京
    西安
    武汉
    ---------------------- 全部城市数据 ----------------------
    阿坝州
    安康
    阿克苏地区
    阿里地区
    阿拉善盟
    阿勒泰地区
    安庆
    安顺
    鞍山
    克孜勒苏州
    安阳
    蚌埠
    白城
    保定
    北海
    宝鸡
    北京
    毕节
    博州
    白山
    百色
    保山
    白沙
    包头
    保亭
    本溪
    巴彦淖尔
    白银
    巴中
    滨州
    亳州
    长春
    昌都
    常德
    成都
    承德
    赤峰
    昌吉州
    五家渠
    昌江
    澄迈
    重庆
    长沙
    常熟

    你可能感兴趣的:(python共同学习,python,爬虫,开发语言)