爬虫课程笔记(四)正则表达式、XML和Xpath

正则表达式

正则表达式的定义:
就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑

常用正则表达式的方法:

  • re.compile(编译)
  • pattern.match(从头找一个)
  • pattern.search(找一个)
  • pattern.findall(找所有)
  • pattern.sub(替换)
    在这里插入图片描述

在这里插入图片描述
替换
在这里插入图片描述
在这里插入图片描述

python中原始字符串r的用法

在这里插入图片描述
在python正则表达中尽可能的使用原始字符串,待匹配的字符串中看到什么就在正则表达式写什么,就不会出现问题
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

内涵段子爬虫(已失效)

# coding=utf-8
import requests
import re
import json

class Neihan:
    def __init__(self):
        self.start_url = "http://neihanshequ.com/"
        self.next_url_temp = "http://neihanshequ.com/joke/?is_json=1&app_name=neihanshequ_web&max_time={}"
        self.headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"}

    def parse_url(self,url):#发送请求
        print(url)
        response = requests.get(url,headers=self.headers)
        return response.content.decode()

    def get_first_page_content_list(self,html_str): #提取第一页的数据
        content_list = re.findall(r"<h1 class=\"title\">.*?<p>(.*?)</p>",html_str,re.S)
        max_time = re.findall("max_time: '(.*?)',",html_str)[0]
        return content_list,max_time

    def save_content_list(self,content_list): #保存
        with open("neihan.txt","a",encoding="utf-8") as f:
            for content in content_list:
                f.write(json.dumps(content,ensure_ascii=False))
                f.write("\n")
        print("保存成功")

    def get_content_list(self,json_str): #提取从第二页开始的json中的数据
        dict_ret = json.loads(json_str)
        data = dict_ret["data"]["data"]
        content_list = [i["group"]["content"] for i in data]
        max_time = dict_ret["data"]["max_time"]
        has_more = dict_ret["data"]["has_more"]
        return content_list,max_time,has_more

    def run(self):#实现主要逻辑
        #1.start_url
        #2.发送请求,获取响应
        html_str = self.parse_url(self.start_url)
        #3.提取数据
        content_lsit,max_time = self.get_first_page_content_list(html_str)
        #4.保存
        self.save_content_list(content_lsit)
        has_more = True #有第二页
        while has_more:
            #5.构造下一页的url地址
            next_url = self.next_url_temp.format(max_time)
            #6.发送请求,获取响应
            json_str = self.parse_url(next_url)
            #7.提取数据,提取max_time
            content_lsit,max_time,has_more = self.get_content_list(json_str)
            #8.保存
            self.save_content_list(content_lsit)
            #9.循环5-8步



if __name__ == '__main__':
    neihan = Neihan()
    neihan.run()

XML和Xpath

XPATH和LXML类库

为什么要学习XPATH和LXML类库

lxml是一款高性能的 Python HTML/XML 解析器,我们可以利用XPath,来快速的==定位特定元素==以及获取节点信息

什么是XPATH:

XPath (XML Path Language) 是一门在 HTML\XML 文档中查找信息的语言,可用来在 HTML\XML 文档中对元素和属性进行遍历。

W3School官方文档:http://www.w3school.com.cn/xpath/index.asp

认识XML

在这里插入图片描述节点的概念:每个XML的标签我们都称之为节点
在这里插入图片描述
XML节点关系
在这里插入图片描述

XPATH节点选择

在这里插入图片描述

节点选取语法

XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
在这里插入图片描述
使用chrome插件选择标签时候,选中时,选中的标签会添加属性class=“xh-highlight”

查找某个特定的节点或者包含某个指定的值的节点
在这里插入图片描述
选择未知节点
在这里插入图片描述
选取若干路径
在这里插入图片描述

xpath的更多语法:
https://msdn.microsoft.com/zh-cn/library/ms256039(v=vs.80).aspx

lxml库

使用入门:
导入lxml 的 etree 库
from lxml import etree
利用etree.HTML,将字符串转化为Element对象
Element对象具有xpath的方法
html = etree.HTML(text)

lxml 可以自动修正 html 代码

# coding=utf-8
from lxml import etree


text = ''' <div> <ul> 
        <li class="item-1"><a>first item</a></li> 
        <li class="item-1"><a href="link2.html">second item</a></li> 
        <li class="item-inactive"><a href="link3.html">third item</a></li> 
        <li class="item-1"><a href="link4.html">fourth item</a></li> 
        <li class="item-0"><a href="link5.html">fifth item</a>  
        </ul> </div> '''

html = etree.HTML(text)
print(html)
#查看element对象中包含的字符串
# print(etree.tostring(html).decode())

#获取class为item-1 li下的a的herf
ret1 = html.xpath("//li[@class='item-1']/a/@href")
print(ret1)

#获取class为item-1 li下的a的文本
ret2 = html.xpath("//li[@class='item-1']/a/text()")
print(ret2)

#每个li是一条新闻,把url和文本组成字典
for href in ret1:
    item = {}
    item["href"] = href
    item["title"] = ret2[ret1.index(href)]
    print(item)

print("*"*100)
#分组,根据li标签进行分组,对每一组继续写xpath
ret3 = html.xpath("//li[@class='item-1']")
print(ret3)
for i in ret3:
    item=  {}
    item["title"] = i.xpath("a/text()")[0] if len(i.xpath("./a/text()"))>0 else None
    item["href"] = i.xpath("./a/@href")[0] if len( i.xpath("./a/@href"))>0 else None
    print(item)


重点

### 正则使用的注意点
- `re.findall("a(.*?)b","str")`,能够返回括号中的内容,括号前后的内容起到定位和过滤的效果

- 原始字符串r,待匹配字符串中有反斜杠的时候,使用r能够忽视反斜杠带来的转义的效果

- 点号默认情况匹配不到`\n`

- `\s`能够匹配空白字符,不仅仅包含空格,还有`\t|\r\n`


### xpath学习重点
- 使用xpath helper或者是chrome中的copy xpath都是从element中提取的数据,但是爬虫获取的是url对应的响应,往往和elements不一样
- 获取文本
  - `a/text()` 获取a下的文本
  - `a//text()` 获取a下的所有标签的文本
  - `//a[text()='下一页']` 选择文本为下一页三个字的a标签

- `@符号`
  - `a/@href`
  - `//ul[@id="detail-list"]`

- `//`
  - 在xpath最前面表示从当前html中任意位置开始选择
  - `li//a` 表示的是li下任何一个标签

### lxml使用注意点
- lxml能够修正HTML代码,但是可能会改错了
  - 使用etree.tostring观察修改之后的html的样子,根据修改之后的html字符串写xpath

- lxml 能够接受bytes和str的字符串

- 提取页面数据的思路
  - 先分组,取到一个包含分组标签的列表
  - 遍历,取其中每一组进行数据的提取,不会造成数据的对应错乱

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值