爬虫四种获取数据的方式

四种爬取页面源代码数据的方式

1.正则表达式re匹配

1.1 导包

import re

1.2 一步到位的匹配

在这里,直接调用re.函数名(匹配规则, 匹配字符串)

# findall:  匹配字符串中所有的符合正则的内容
result = re.findall('a', '我是一个abcdefg')
print(result) # ['a']
result = re.findall(r"\d+", "我的电话号是:10086, 我女朋友的电话是:10010")
print(result) # ['10086', '10010']

# finditer: 匹配字符串中所有的内容[返回的是迭代器], 从迭代器中拿到内容需要.group()
it = re.finditer(r"\d+", "我的电话号是:10086, 我女朋友的电话是:10010")
for i in it:
    # group是从匹配到的结果中拿到具体数据,而非迭代器元素
    print(i.group()) # 10086 10010

# search, 找到一个结果就返回, 返回的结果是match对象. 拿数据需要.group()
s = re.search(r"\d+", "我的电话号是:10086, 我女朋友的电话是:10010")
print(s.group()) # 10086

# match是从头开始匹配,类似在正则前加上^
s = re.match(r"\d+", "10086, 我女朋友的电话是:10010")
print(s.group()) # 10086

1.3 分步匹配及示例

  1. re.compile来构建自己需要的正则表达式规则
obj = re.compile(r"<div class='.*?'><span id='(?P<id>\d+)'>(?P<wahaha>.*?)</span></div>", re.S)  # re.S: 让.能匹配换行符

其中:

.*?代表惰性匹配,即匹配到第一个后就不再继续匹配,在爬虫中最为常见,其余详见正则表达式的使用

(?P<wahaha>.*?) # 小括号将.*?括在里面,然后?P<wahaha>表示将.*?匹配到的内容命名为wahaha,这在后续正则表达式的函数中运用很多
  1. 执行各种常用函数

简单举例:

# 预加载正则表达式
obj = re.compile(r"\d+")

ret = obj.finditer("我的电话号是:10086, 我女朋友的电话是:10010")
for it in ret:
    print(it.group()) # 10086 10010

ret = obj.findall("呵呵哒, 我就不信你不换我1000000000")
print(ret) # 1000000000

2.bs4匹配

2.1 导包

import requests
from bs4 import BeautifulSoup

2.2 常见函数与简单示例

2.2.1 常见函数find与find_all
# 解析数据
# 1. 把页面源代码交给BeautifulSoup进行处理, 生成bs对象
resp = requests.get(url)
page = BeautifulSoup(resp.text, "html.parser")  # 指定html解析器
# 2. 从bs对象中查找数据
# find(标签, 属性=值) 仅找一个
# find_all(标签, 属性=值) 找到所有匹配的
table = page.find("table", class_="hq_table")  # class是python的关键字,因此用class_
table = page.find("table", attrs={"class": "hq_table"})  # 和上一行是一个意思. 此时可以避免class
# 拿到所有数据行 过滤掉表头
trs = table.find_all("tr")[1:]
for tr in trs:  # 每一行
    tds = tr.find_all("td")  # 拿到每行中的所有td 是一个列表
    name = tds[0].text  # .text 表示拿到被标签标记的内容
    low = tds[1].text  # .text 表示拿到被标签标记的内容
    avg = tds[2].text  # .text 表示拿到被标签标记的内容
    high = tds[3].text  # .text 表示拿到被标签标记的内容
    gui = tds[4].text  # .text 表示拿到被标签标记的内容
    kind = tds[5].text  # .text 表示拿到被标签标记的内容
    date = tds[6].text  # .text 表示拿到被标签标记的内容
    csvwriter.writerow([name, low, avg, high, gui, kind, date])
2.2.2 简单示例
# 示例2
html = """
<ul>
<li><a href="zhangwuji.com">张⽆忌</a></li>
<li id="abc"><a href="zhouxingchi.com">周星
驰</a></li>
<li><a href="zhubajie.com">猪⼋戒</a></li>
<li><a href="wuzetian.com">武则天</a></li>
</ul>
"""
from bs4 import BeautifulSoup
page = BeautifulSoup(html, "html.parser")
lis = page.find_all("li")
for li in lis:
print(li.find("a").get("href")) # get代表获取该标签下某一属性的值 text则直接调用.text

3.XPath匹配

3.1 导包

from lxml import etree

3.2 各种语法含义

xml = """
<book>
    <id>1</id>
    <name>野花遍地香</name>
    <price>1.23</price>
    <nick>臭豆腐</nick>
    <author>
        <nick id="10086">周大强</nick>
        <nick id="10010">周芷若</nick>
        <nick class="joy">周杰伦</nick>
        <nick class="jolin">蔡依林</nick>
        <div>
            <nick>热热热热热1</nick>
        </div>
        <span>
            <nick>热热热热热2</nick>
        </span>
    </author>

    <partner>
        <nick id="ppc">胖胖陈</nick>
        <nick id="ppbc">胖胖不陈</nick>
    </partner>
</book>
"""
et = etree.XML(xml) # 生成
result = et.xpath("/book") # /表示根节点
result = et.xpath("/book/name") # 中间/表示下一层
result = et.xpath("/book/name/text()") # text()表示文本
result = et.xpath("/book//nick") # //表示找所有的相应标签,即可跳所有层
result = et.xpath("/book/*/nick") # /*/表示仅跳一层 非所有层 *代表通配符
result = et.xpath("/book/author/nick[@class='jay']/text()") # [@class='jay']表示找class为jay的标签
result = et.xpath("/book/author/nick/@class") # /@class表示找nick中的class属性值
print(result)

3.3 常用函数及语法含义

from lxml import etree
html = """
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Title</title>
    </head>
    <body>
        <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>
"""
et = etree.HTML(html) # 这边是解析HTML 用的HTML()
result = et.xpath('/html/body/ul/li[2]/a/text()') # ['谷歌'] li[2]表示第二个li标签,这个2是从1开始,而非从0开始
# print(result)
li_list = et.xpath('//li')
for li in li_list:
    href = li.xpath('./a/@href') # ./表示当前节点
    text = li.xpath('./a/text()') # ./表示当前节点
    print(href, text)

4.PyQuery匹配

4.1 导包

from pyquery import PyQuery

4.2 常用函数及语法含义

# 导入PyQuery
p = PyQuery(html)
# p是一个PyQuery类型的对象,而非字符串
print(p)

# 与css选择器的语法一致
li = p("li")
print(li)

# p是一个PyQuery类型的对象,而非字符串
a = p("a")

# 可以连续选择
a = p("li")("a")

# 后代选择器 与上者一致
a = p("li a")
print(a)

# . 意味着选择类值为aaa的标签
a = p(".aaa")
a = p(".aaa a")
# # 意味着选择id值为qq的标签
a = p("#qq a")

# 我们可以用attr来选择属性值
href = p("#qq a").attr("href")
# 我们可以用text()来选择文本值
text = p("#qq a").text()
print(href)
print(text)

# 但如果我们要得到li标签下所有a标签中的href属性值,不能用以下方法
href = p("li a").attr("href")
# 只能得到一个
print(href) # result: http://www.google.com
# 我们需要使用items()方法来得到一个迭代器
items = p("li a").items()
print(items) # result:<generator object PyQuery.items at 0x00000224E0D490B0>
for item in items:
    # item也是一个PyQuery对象
    # print(type(item))
    href = item.attr("href")
    text = item.text()
    print(href)
    print(text)
    print('------')

# 总结一下
# attr()用于获取属性值
# items()用于获取所有匹配到的标签 是一个迭代器
# text()用于获取文本信息
# html()用于获取指定标签下的所有值
div = '''
<div><a href="test">test</a></div>
'''
div = PyQuery(div)
html = div("div").html()
text = div("div").text()
print(html) # <a href="test">test</a>
print(text) # test

4.3 一些可改变HTML结构的函数

from pyquery import PyQuery

html = '''
<html>
    <div class="aaa">哒哒哒</div>
    <div class="bbb">嘟嘟嘟</div>
</html>
'''
p = PyQuery(html)
# 在 <div class="aaa">哒哒哒</div> 后 加入 <div class="ccc">吼吼吼</div>
p("div.aaa").after('''<div class="ccc">吼吼吼</div>\n''')
print(p)
# 在 <div class="aaa">哒哒哒</div> 内 加入 <span class="ddd">哈哈哈</span>
p("div.aaa").append('''<span class="ddd">哈哈哈</span>''')
print(p)
# 将 <div class="bbb"> 中的class属性值改为aaa
p("div.bbb").attr("class", "aaa")
# 给 <div class="aaa"> 加入新属性id,值为123456
p("div.aaa").attr("id", "123456")
print(p)
# 从 <div class="aaa"> 中移除id属性
p("div.aaa").remove_attr("id")
print(p)
# 移除类属性值为aaa的标签
p("div.aaa").remove()
print(p)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值