爬虫-数据解析

目录

数据解析

一. re解析

1.1 正则

1.2 re模块

1.3 应用在爬虫

二. bs4解析

2.1 HTML基本结构

2.2 CSS选择器

2.2.1. css语法规则:

2.2.2. css选择器(重点)

2.3 bs4解析

2.3.1 通用查询方案

2.3.2 利用css选择器来获取页面内容

三. xpath解析

3.1 xpath语法

3.2 xpath实战案例(重点)


数据解析

在上一节中, 我们基本上掌握了抓取整个网页的基本技能. 但是呢, 大多数情况下, 我们并不需要整个网页的内容, 只是需要那么一小部分. 怎么办呢? 这就涉及到了数据提取的问题.

本课程中, 提供三种解析方式:

  1. re解析 (必修)

  2. bs4解析

  3. xpath解析(必修)

以上三种方案都可以从HTML中提取到你需要的内容, 这三种方式可以混合进行使用, 完全以结果做导向, 只要能拿到你想要的数据. 用什么方案并不重要. 当你掌握了这些之后. 再考虑性能的问题.

一. re解析

1.1 正则

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

我们抓取到的网页源代码本质上就是一个超长的字符串, 想从里面提取内容.用正则再合适不过了.

正则的优点: 速度快, 效率高, 准确性高 正则的缺点: 新手上手难度有点儿高.

不过只要掌握了正则编写的逻辑关系, 写出一个提取页面内容的正则其实并不复杂

正则的语法: 使用元字符进行排列组合用来匹配字符串 在线测试正则表达式在线正则表达式测试

元字符: 具有固定含义的特殊符号 常用元字符:

 .     √匹配除换行符以外的任意字符,  未来在python的re模块中是一个坑. 
 \w    √匹配字母或数字或下划线.
 \s    匹配任意的空白符
 \d    √匹配数字
 \n    匹配一个换行符
 \t    匹配一个制表符
 
 ^     匹配字符串的开始
 $     匹配字符串的结尾
 
 \W    匹配非字母或数字或下划线
 \D    匹配非数字
 \S    匹配非空白符
 a|b   匹配字符a或字符b
 ()    √匹配括号内的表达式,也表示一个组
 [...]    √匹配字符组中的字符
 [^...]    匹配除了字符组中字符的所有字符

量词: 控制前面的元字符出现的次数

 *    重复零次或更多次
 +    重复一次或更多次
 ?    重复零次或一次
 {n}    重复n次 
 {n,}    重复n次或更多次 
 {n,m}    重复n到m次

贪婪匹配和惰性匹配(重点)

 .*     贪婪匹配,  尽可能多的去匹配结果
 .*?    惰性匹配,  尽可能少的去匹配结果 -> 回溯

这两个要着重的说一下. 因为我们写爬虫用的最多的就是这个惰性匹配.

先看案例

 str: 玩儿吃鸡游戏, 晚上一起上游戏, 干嘛呢? 打游戏啊
 reg: 玩儿.*?游戏
 
 此时匹配的是: 玩儿吃鸡游戏
 
 reg: 玩儿.*游戏   
 此时匹配的是: 玩儿吃鸡游戏, 晚上一起上游戏, 干嘛呢? 打游戏    
     
                 
 str: <div>胡辣汤</div>
 reg: <.*>
 结果: <div>胡辣汤</div>
 
 
 str: <div>胡辣汤</div>
 reg: <.*?>
 结果: 
     <div>
     </div>
 
 str: <div class="abc"><div>胡辣汤</div><div>饭团</div></div>
 reg: <div>.*?</div>
 结果:
     <div>胡辣汤</div>
     <div>饭团</div>
​

所以我们能发现这样一个规律: .*? 表示尽可能少的匹配, .*表示尽可能多的匹配, 暂时先记住这个规律. 后面写爬虫会用到

1.2 re模块

那么接下来的问题是, 正则我会写了, 怎么在python程序中使用正则呢? 答案是re模块

re模块中我们只需要记住这么几个功能就够我们使用了.

  1. findall 查找所有. 返回list

    lst = re.findall("m", "mai le fo len, mai ni mei!") 
    print(lst)    # ['m', 'm', 'm'] 
    lst = re.findall(r"\d+", "5点之前. 你要给我5000万")
    print(lst)   # ['5', '5000']
  2. search 会进行匹配. 但是如果匹配到了第一个结果. 就会返回这个结果. 如果匹配不上search返回的则是None

    ret = re.search(r'\d', '5点之前. 你要给我5000万').group()
    print(ret) # 5
  3. match 只能从字符串的开头进行匹配(再见)

    ret = re.match('a', 'abc').group()  
    print(ret)     # a
  4. finditer 和findall差不多. 只不过这时返回的是迭代器(重点)

    it = re.finditer("m", "mai le fo len, mai ni mei!")
    for el in it:
        print(el.group()) # 依然需要分组
  5. compile() 可以将一个长长的正则进行预加载. 方便后面的使用

    obj = re.compile(r'\d{3}')  # 将正则表达式编译成为一个 正则表达式对象, 规则要匹配的是3个数字
    ret = obj.search('abc123eeee') # 正则表达式对象调用search, 参数为待匹配的字符串
    print(ret.group())  # 结果: 123
  6. 正则中的内容如何单独提取?

    单独获取到正则中的具体内容可以给分组起名字

    s = """
    <div class='西游记'><span id='10010'>中国联通</span></div>
    """
    obj = re.compile(r"<span id='(?P<id>\d+)'>(?P<name>\w+)</span>", re.S)
    ​
    result = obj.search(s)
    print(result.group())  # 结果: <span id='10010'>中国联通</span>
    print(result.group("id"))  # 结果: 10010 # 获取id组的内容
    print(result.group("name"))  # 结果: 中国联通 # 获取name组的内容

    这里可以看到我们可以通过使用分组. 来对正则匹配到的内容进一步的进行筛选.

  7. 正则表达式本身是用来提取字符串中的内容的. 也可以用作字符串的替换

    import re
    r = re.split(r"\d+", "我今年19岁了, 你知道么, 19岁就已经很大了. 周杰伦20岁就得奖了")
    print(r)  # ['我今年', '岁了, 你知道么, ', '岁就已经很大了. 周杰伦', '岁就得奖了']
    # 替换
    r = re.sub(r"\d+", "18", "我今年19岁了, 你知道么, 19岁就已经很大了. 周杰伦20岁就得奖了")
    print(r)  # 我今年18岁了, 你知道么, 18岁就已经很大了. 周杰伦18岁就得奖了
    ​

哦了. 正则. 这些东西够用了.

1.3 应用在爬虫

我们找个网站试试水, http://www.animationcritics.com/chinese_aniamtion.html 难度较大

import requests
import re
import time
​
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36"
}
​
resp = requests.get("http://www.animationcritics.com/chinese_aniamtion.html", headers=headers)
​
obj = re.compile(r'''<li style="margin-bottom:10px;">.*?articleid="\d+"'''+
'.*?href="(?P<href>.*?)" title="(?P<title>.*?)">.*?</a>', re.S)
​
org_obj = re.compile(r'<span class="org_txt">来源:</span>(?P<org>.*?)</span>', re.S)
aut_obj = re.compile(r'<span class="aut_txt">作者:</span>(?P<aut>.*?)</span>', re.S)
pub_obj = re.compile(r'<span class="pub_txt">发布时间: </span>(?P<pub>.*?)</span>', re.S)
​
section_obj = re.compile(r"<section.*?>(?P<content>.*?)</section>")
​
page_source = resp.text
results = obj.finditer(page_source)
for item in results:
    href = item.group("href")
    title = item.group("title")
​
    child_resp = requests.get(href, headers=headers)
    child_page_source = child_resp.text
​
    org_result = org_obj.search(child_page_source)
    if not org_result:
        org = ""
    else:
        org = org_result.group("org")
​
    aut_result = aut_obj.search(child_page_source)
    if not aut_result:
        aut = ""
    else:
        aut = aut_result.group("aut")
​
    pub_result = pub_obj.search(child_page_source)
    if not pub_result:
        pub = ""
    else:
        pub = pub_result.group("pub")
​
    sections = []
    section_result = section_obj.finditer(child_page_source, re.S)
    for item in section_result:
        content = item.group('content')
        sections.append(content.strip())
​
    print(title, org, aut, pub)
    print("===========================================================================")
    section = re.sub(r"<.*?>", "", "".join(sections))  # 正则替换.参数1:正则, 参数2:替换后内容, 参数3:源字符串
    print(section)
    time.sleep(2)
​
    # 作业,"《笨鸟大冒险》:不能因为中文配音,就说这是国产片啊" 这一篇文章出不来. 请问为什么? 怎么调整?
​

二. bs4解析

估计看到这里. 你应该是半崩溃状态. 用正则提取东西实在太痛苦了. 有没有那种能直接提取标签的方法. 有的. 但是在学习新方案之前. 我们必须要了解和知道, 网页的组成(HTML, CSS). 了解完这两个东西之后. 再学bs4, xpath这些就容易很多了.

2.1 HTML基本结构

HTML(Hyper Text Markup Language)超文本标记语言, 是我们编写网页的最基本也是最核心的一种语言. 其语法规则就是用不同的标签对网页上的内容进行标记, 从而使网页显示出不同的展示效果.

<h1>
    我爱你
</h1>

上述代码的含义是在页面中显示"我爱你"三个字, 但是我爱你三个字被"<h1>"和"</h1>"标记了. 白话就是被括起来了. 被H1这个标签括起来了. 这个时候. 浏览器在展示的时候就会让我爱你变粗变大. 俗称标题, 所以HTML的语法就是用类似这样的标签对页面内容进行标记. 不同的标签表现出来的效果也是不一样的.

h1: 一级标题
h2: 二级标题
p: 段落
font: 字体(被废弃了, 但能用)
body: 主体

这里只是给小白们简单科普一下, 其实HTML标签还有很多很多的. 我们不需要一一列举(这是爬虫课, 不是前端课).

OK~ 标签我们明白了, 接下来就是属性了.

<h1>
    我爱你
</h1>
<h1 align='right'>
    我爱你妹
</h1>

有意思了. 我们发现在标签中还可以给出xxx=xxx这样的东西. 那么它又是什么呢? 又该如何解读呢?

首先, 这两个标签都是h1标签, 都是一级标题, 但是下面这个会显示在右边. 也就是说, 通过xxx=xxx这种形式对h1标签进一步的说明了. 那么这种语法在html中被称为标签的属性. 并且属性可以有很多个. 例如:

<body text="green" bgcolor="#eee">
    你看我的颜色. 贼健康
</body>

总结, html语法:

<标签 属性1="值" 属性2="值">
    被标记的内容
</标签>
或
<标签 属性1="值" 属性2="值"/>
   

对于语法层面, 我们知道这么多就够了. 大多数情况下, 我们并不用关心divspan有什么区别. 也不用关心section是什么. 但是有几个标签. 我们是必须要知道的. 因为未来, 我们会高密度的和这几个标签做斗争.

  1. a 超链接

  2. img 图片

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href="http://www.baidu.com">我是百度</a>
    <a href="myself.html">我是自己</a>
    <a href="dddd/myself.html">我是自己</a>
    <img src="https://mmbiz.qpic.cn/mmbiz/ZKGHmo3MibQUhB9O7E0b05wBDuP1beR86kcXtFsPUZVnanPW2Sjmwiaia0ibICJt4Q8Q7RDyF3bthpciaBuOwcgEWZg/0"/>
</body>
</html>
​

2.2 CSS选择器

CSS全称 层叠样式表(Cascading Style Sheets), 主要用来定义页面内容展示效果的一门语言.

HTML: 页面骨架. 素颜 CSS: 页面效果美化+布局. 美妆+滤镜

2.2.1. css语法规则:
  1. 通过style属性来编写样式

  2. 通过style标签中定义选择器. 然后使用选择器的来选择页面上的元素, 添加样式

  3. css文件中编写样式, 通过link引入该文件

2.2.2. css选择器(重点)
1. id选择器        #id值
2. 标签选择器       标签
3. 类选择器         .
4. 选择器分组       ,
5. 后代选择器       空格
6. 子选择器         父 > 子
7. 属性选择器       [属性=值]
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        /*标签选择器, 选择页面上的标签, 添加样式*/
        div{
            width:400px;
            height:300px;
            border: 1px solid red;
            float: left;
            font-size: 1cm;
        }
​
        /*id选择器, 根据页面上的id值.选择标签*/
        #jay{
            color:green;
        }
​
        /*类选择器, 根据页面上的class值.选择标签*/
        .wlh{
            color:yellowgreen;
        }
​
        /*类选择器, 根据页面上的class值.选择标签*/
        /*
            解读: 寻找class是wlh的p标签
            <p class='wlh'></p>
        */
        p.wlh{
            color:lightseagreen;
        }
​
        /*标签选择器, 根据页面上的标签名.选择标签*/
        article{
            color:darkgreen;
        }
​
        /*
            选择器分组, 符合以下条件的选择器被选择
            解读: 多个选择器一起生效
        */
        .zu1,.zu2{
            color: orange;
        }
​
        /*
        后代选择器, 符合该结构的页面内容被选择
         */
        section span{
            color: springgreen;
        }
​
        /*
        子选择器, 符合该结构的父子关系的被选择
         */
        strong > span{
            color: lawngreen;
        }
​
        /*
        符合 属性=值 的标签被选择
        解读: code标签中, abc='haha'的被添加样式
         */
        code[abc='haha']{
            color:mediumspringgreen;
        }
    </style>
</head>
<body>
    <div>
        id选择器
        <span id="jay">我是周杰伦, 我也是id选择器</span>
    </div>
    <div>类选择器
        <span class="wlh">我是王力宏, 我也是类选择器</span>
        <section class="wlh">我是一样也是王力宏, 我也是类选择器</section>
        <p class="wlh">我还没那么绿</p>
    </div>
    <div>标签选择器
        <article>我也是article, 我是分组选择器</article>
    </div>
    <div>选择器分组
        <article class="zu1">我是article, 我是标签选择器</article>
        <section class="zu2">我是section, 我是标签选择器</section>
    </div>
    <div>后代选择器
        <section><span>一样是吃</span></section>
        <span>一样是吃</span>
    </div>
    <div>子选择器
        <strong><span>一样是喝</span></strong>
        <strong><i><span>一样是喝</span></i></strong>
    </div>
    <div>属性选择器
        <code abc="haha">代码</code>
        <code>代码</code>
        <code abc="haha">代码</code>
        <code>带带吗</code>
    </div>
</body>
</html>

注意, 在class里可能会有多个值.  表示多个选择器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            border: 1px solid red;
        }
        .jay{
            color:red;
        }
        .wlh{
            background:pink;
        }
    </style>
</head>
<body>
    <!-- 这里是两个选择器的意思. -->
    <div class="jay wlh">吃饭了么</div>
    <div class="jay">吃多了吧</div>
</body>
</html>

2.3 bs4解析

有了这些基础了. 我们尝试着学学这个叫bs4的东西. bs4 的逻辑很简单. 直接用标签和属性来选择页面上的标签

bs4是一个第三方模块. 需要单独安装

pip install bs4  # BeautifulSoup

2.3.1 通用查询方案

关于bs4, 本质上我们知道两个东西就好, 一个是find,另一个是find_all, 从名字上看. 一个是查找一个, 另一个是查找所有.

  1. find, 在页面中查找一个结果, 找到了就返回

  2. find_all, 在页面中查找一堆结果. 找完了才返回

这两个功能拥有相同的参数结构. 学一个即可

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

上个案例试试

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
​
​
url = "https://desk.zol.com.cn/pc/"
headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36"
}
# 发送请求, 获取页面源代码
resp = requests.get(url, headers=headers)
resp.encoding = 'gbk'  # 设置一下字符集
# 1. 创建BeautifulSoup的对象
main_soup = BeautifulSoup(resp.text, "html.parser")
# 2. 找到超链接, 请注意.这里面的属性拼接,多少会和页面稍微有一些细微的差别.
a_list = main_soup.find("ul", attrs={"class": "pic-list2 clearfix"}).find_all("a")
# 3. 循环出每一个超链接
for a in a_list:
    # 4.1 拿到href, 也就是子页面的url
    href = a.get("href")
    # 4.2 获取超链接中的文本信息
    content = a.text
    print("没啥用,只是给你演示如何获取文本", content)
    # 5. 剔除特殊项
    if href.endswith(".exe"):  # 垃圾客户端. 坑我
        continue
    # 6. 域名拼接
    href = urljoin(url, href)
​
    # 7. 剩下的就是套娃了
    child_resp = requests.get(href, headers=headers)
    child_resp.encoding = 'gbk'
    child_soup = BeautifulSoup(child_resp.text, "html.parser")
    # print(child_resp.text)  # 适当的打印,可以帮助你调BUG
    img = child_soup.find("img", attrs={"id": "bigImg"})
    img_src = img.get("src")
​
    # 下载图片
    img_resp = requests.get(img_src, headers=headers)
    file_name = img_src.split("/")[-1]
    with open(file_name, mode="wb") as f:
        f.write(img_resp.content)
    print("下载完一张图片了")
2.3.2 利用css选择器来获取页面内容

关于选择器. 这里我们讲两个功能

  1. select_one(选择器) 使用选择器获取html文档中的标签, 拿一个

  2. select(选择器) 使用选择器获取html文档中的标签, 拿一堆

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
​
​
url = "https://desk.zol.com.cn/pc/"
headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36"
}
# 发送请求, 获取页面源代码
resp = requests.get(url, headers=headers)
resp.encoding = 'gbk'  # 设置一下字符集
# 1. 创建BeautifulSoup的对象
main_soup = BeautifulSoup(resp.text, "html.parser")
# 2. 找到超链接, 请注意.这里面的属性拼接,多少会和页面稍微有一些细微的差别.
a_list = main_soup.select("ul.pic-list2 a")
# 3. 循环出每一个超链接
for a in a_list:
    # 4.1 拿到href, 也就是子页面的url
    href = a.get("href")
    # 4.2 获取超链接中的文本信息
    content = a.text
    print("没啥用,只是给你演示如何获取文本", content)
    # 5. 剔除特殊项
    if href.endswith(".exe"):  # 垃圾客户端. 坑我
        continue
    # 6. 域名拼接
    href = urljoin(url, href)
​
    # 7. 剩下的就是套娃了
    child_resp = requests.get(href, headers=headers)
    child_resp.encoding = 'gbk'
    child_soup = BeautifulSoup(child_resp.text, "html.parser")
    # print(child_resp.text)  # 适当的打印,可以帮助你调BUG
    img = child_soup.select_one("#bigImg")
    img_src = img.get("src")
​
    # 下载图片
    img_resp = requests.get(img_src, headers=headers)
    file_name = img_src.split("/")[-1]
    with open(file_name, mode="wb") as f:
        f.write(img_resp.content)
    print("下载完一张图片了")
​

三. xpath解析

xpath是一种非常简单好用的页面提取方案. 使用前. 请安装好lxml模块

pip install lxml

3.1 xpath语法

我们给出一段测试用的HTML代码.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Title</title>
</head>
<body>
    <div>
        <p>一个很厉害的人</p>
        <ol>
            <li id="10086">周大强</li>
            <li id="10010">周芷若</li>
            <li class="joy">周杰伦</li>
            <li class="jolin">蔡依林</li>
            <ol>
                <li>阿信</li>
                <li>信</li>
                <li>信不信</li>
            </ol>
        </ol>
    </div>
    <hr />
    <ul>
        <li><a href="http://www.baidu.com">百度</a></li>
        <li><a href="http://www.google.com">谷歌</a></li>
        <li><a href="http://www.sogou.com">搜狗</a></li>
    </ul>
    <ol>
        <li><a href="feiji">飞机</a></li>
        <li><a href="dapao">大炮</a></li>
        <li><a href="huoche">火车</a></li>
    </ol>
    <div class="job">李嘉诚</div>
    <div class="common">胡辣汤</div>
</body>
</html>

xpath 上半场

from lxml import etree
​
# 加载HTML
f = open("xpath测试.html", mode='r', encoding='utf-8')
page_source = f.read()
​
# 和bs4一样, 把HTML交给etree
hm = etree.HTML(page_source)  # type:etree._Element
# xpath各种用法
# 节点: 每个HTML标签叫节点
# 最外层节点: 根节点
# 内层节点: 子节点
# 父子节点: <爹><子></子></爹>
​
html = hm.xpath("/html")  # /根
print(html)  # 看一眼标签名(测试用, 不用记住)
​
body = hm.xpath("/html/body")  # 第二个/表示子节点
print(body)
​
# 接下来这句话请记住, xpath提取到的内容不论多少, 都会返回列表
p = hm.xpath("/html/body/div/p/text()")  # 想要p里面的文本
print(p)  # 列表
print(p[0])  # 要么取0.
print("".join(p))  # 要么用join()进行合并.
​
# 如果页面结构非常复杂. 这样一层一层数下来. 过年了
# xpath我们还可以用相对定位
p = hm.xpath("//p/text()")  # // 表示在页面任意位置找
print(p)  # 依然有效
​
# 我想找到 `周大强`, `周芷若`,`周杰伦`,`周大强`,`蔡依林`
li = hm.xpath("//div/ol/li/text()")
print(li)
​
# 我想找到 `一个很厉害的人`后面ol中所有的文本
li = hm.xpath("//div/ol//text()")  # 第二个//表示所有
# 请注意. 这里多了很多空白,一般我们提取一篇文章的时候,会用这种.
# 结合字符串各种操作. 这些东西应该难不倒各位.
print(li)
print("".join(li).replace(" ", "").replace("\n", ""))

xpath下半场(重点)

from lxml import etree
​
# 加载HTML
f = open("xpath测试.html", mode='r', encoding='utf-8')
page_source = f.read()
​
# 和bs4一样, 把HTML交给etree
hm = etree.HTML(page_source)  # type:etree._Element
​
# 重点:根据位置数元素
# 我想要`周芷若`, 分析角度: 它是ol里第二个li
li = hm.xpath("//ol/li[2]/text()")
print(li)  # 这里莫名其妙带出了`信`, 请思考为什么? 请思考怎么干掉`信`
​
# 我想单独找`信`聊聊
li = hm.xpath("//ol/ol/li[2]/text()")
print(li)
​
# 重点:根据属性筛选元素
# 我想要id=10086的li标签中的内容0
li = hm.xpath("//li[@id='10086']/text()")
print(li)
​
# 我想要class是joy的内容
li = hm.xpath("//*[@class='joy']/text()")
print(li)
​
# 我想要有class的li的内容
li = hm.xpath("//*[@class]/text()")
print(li)
​
# 我想和`啊信`,`信`,`信不信`单独聊聊
li_list = hm.xpath("//ol/ol/li")
for li in li_list:
    print(li.xpath("./text()"))  # ./表示当前节点, 也就是li
​
# 提取`百度`, 谷歌, 搜狗的超链接href属性
li_list = hm.xpath("//ul/li")
for li in li_list:
    print(li.xpath("./a/text()"))  # ./表示当前节点, 也就是li
    print(li.xpath("./a/@href"))  # @href 表示提取属性
​
# 我想要`火车`
li = hm.xpath("//body/ol/li[last()]/a/text()")  # last() 拿到最后一个
print(li)
​
f.close()

3.2 xpath实战案例(重点)

我们选择一个网站. 尝试着进行数据提取

2019 中国票房 | 中国票房 | 中国电影票房排行榜 抓取2019年的电影票房数据.

import requests
from lxml import etree
​
​
url = "http://www.boxofficecn.com/boxoffice2019"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36"
}
resp = requests.get(url, headers=headers)
​
tree = etree.HTML(resp.text)  # 加载页面源代码
​
# 提取数据
# 这个xpath不是随便写的. 你要找到你的`单条数据`的边界
trs = tree.xpath("//table/tbody/tr")[1:-1]
for tr in trs:
    num = tr.xpath("./td[1]/text()")  # 编号
    year = tr.xpath("./td[2]//text()")  # 年份
    name = tr.xpath("./td[3]//text()")  # 名称
    money = tr.xpath("./td[4]/text()")  # 票房
    print(num, year, name, money)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值