学习总结week5_4lxml

python- lxml和多线程

1. xpath语法 (通用)

1.树:整个html(xml)代码结构就是树结构
2.根节点(根元素):html或者xml最外面的那个标签(元素)
3.节点:组成树结构中的每一个标签
4.节点内容:标签内容
5.节点属性:标签属性

xml数据格式

xml和json一样是一种通用数据格式(大部分编程语言都支持)
xml是通过标签(元素)的标签内容和标签属性来保存数据的
xpath语法
1.创建树结构获取树的根节点
etree.XML(xml数据)
etree.HTML(html数据)

from lxml import etree
f = open('files/date.xml', encoding='utf-8')
root = etree.XML(f.read())
f.close()
2.根据xpath获取指定标签

节点对象.xpath(路径) - 返回路径对应的所有的标签,返回值是列表,列表中的元素是标签对象(节点对象)
路径的写法:
1.绝对路径: 用’/‘开头的路径 /标签在树结构中的全路径(路径必须从根节点开始写)
2.相对路径: 路径开头用’.‘表示当前节点,’…'表示当前节点的上层节点
3.全路径: 用两个//开头的路径 - 在整个树中获取标签

注意:绝对路径和全路径的写法以及查找方法和是用谁去点的xpath无关
./可省略

res = root.xpath('/supermarket/staffs/staff/name/text()')
print(res)

res = root.xpath('./staffs/staff/name/text()')
print(res)
staff1 = root.xpath('./staffs/staff')[0]
print(staff1.xpath('./name/text()'))

res = root.xpath('//name/text()')
print(res)
res = staff1.xpath('//goods/name/text()')
print(res)
3.获取标签内容

节点对象.xpath(获取标签的路径/text()) - 获取指定路径下的所有标签的标签内容

4.获取标签属性值

节点对象.xpath(获取标签的路径/@属性名)

res = root.xpath('/supermarket/@name')
print(res)
res = root.xpath('//staff/@id')
print(res)
5.谓语

位置相关谓语
[N] - 第N个
[last()] - 最后一个
[last()-N] - 倒数第N+1个
[position()>N]、[position()<N]、[position()<=N]、[position()>=N]

res = root.xpath('//staff[1]/name/text()')
print(res)
res = root.xpath('//staff[last()-1]/name/text()')[0]
print(res)
res = root.xpath('//staff[position()>=3]/name/text()')
print(res)
6.属性相关谓语

[@属性名=属性值] - 获取指定属性是指定值的标签
[@属性名] - 获取指定属性名的标签

res = root.xpath('//staff[@class="c1"]/name/text()')
print(res)
res = root.xpath('//staff[@id="s003"]/name/text()')
print(res)
res = root.xpath('//staff[@id="s003"]/name/text()')
print(res)
res = root.xpath('//goods[@discount]/name/text()')
print(res)
7.子标签内容相关谓语 - 根据子标签内容来筛选标签

[子标签名>数据]
[子标签名<数据]
[子标签名>=数据]
[子标签名<=数据]
[子标签名=数据]

res = root.xpath('//goods[price>=2]/name/text()')
print(res)

# 通配符   -   写路径的时候用*表示任意标签或者任意属性
res = root.xpath('//staff[@id="s001"]/*/text()')
print(res)
res = root.xpath('//*[@id="s001"]/*/text()')
print(res)
res = root.xpath('/supermarket/@*')
print(res)
8.若干路径 - |
路径1|路径2   -   同时获取路径1和路径2的内容
res = root.xpath('//goods[price>=2]/name/text()|//staff[@id="s001"]/*/text()')
print(res)

二.多线程基本理论

进程:一个正在运行的应用程序就是一个进程,每个进程军运行在其专门且受保护的内存空间中
线程:线程是进程执行任务的基本单元(一个进程中的任务都是在线程中执行的)
(进程是车间,线程是工人)
一个进程中默认有一个线程(主线程)

线程的特点:
如果在一个线程中执行多个任务,任务是串行执行的(按顺序一个一个执行)
当一个程序中有多个任务,若只有一个线程,程序的执行效率会很低

多线程
一个进程中有多个线程就是多线程
多线程执行任务时,多个任务可以同时(并行)执行

多线程原理
一个cpu同一时间只能调度一个线程, 多线程其实是cpu快速的在多个线程之间切换,造成多个线程同时执行的假象
(提高cpu利用率)

python使用多线程的方法
一个进程默认只有一个线程(主线程),除此之外的线程都叫子线程
python中若需要子线程,必须创建线程类(Thread)的对象

from threading import Thread
from time import sleep
from datetime import datetime

def download(name):
    print(f'{name}开始下载:{datetime.now()}')
    sleep(2)
    print(f'{name}下载完成:{datetime.now()}')


if __name__ == '__main__':
    # 单线程
    # download('肖申克的救赎')
    # download('霸王别姬')
    # download('阿甘正传')

    # 1.使用3个子线程下载3个电影
    # 创建线程对象
    """
    Thread(target=函数, args=元组)
    函数  -   可以是普通函数名,也可以是匿名函数 这个函数就是需要子线程中执行的任务
    元组  -   元组中的元素就是在子线程中调用target对应的函数的时候需要的参数
    
    """
    t1 = Thread(target=download, args=('肖申克的救赎',))
    t2 = Thread(target=download, args=('霸王别姬',))
    t3 = Thread(target=download, args=('阿甘正传',))

    # 启动线程    -   让子线程调对应的函数
    t1.start()
    t2.start()
    t3.start()

爬取豆瓣10页数据 - 多线程

import csv
import requests
from lxml import etree
from threading import Thread
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
}


def get_date(page):
    url = f'https://movie.douban.com/top250?start={page}&filter='
    response = requests.get(url, headers=headers)
    root = etree.HTML(response.text)
    name = root.xpath('//div[@class="info"]/div[@class="hd"]/a/span[1]/text()')
    intro = root.xpath('//div[@class="info"]/div[@class="bd"]/p[@class="quote"]/span/text()')
    all_date = map(lambda i1, i2: [i1, i2], name, intro)

    with open('files/2.csv', 'a', encoding='utf-8', newline='') as f:
        w = csv.writer(f)
        w.writerows(all_date)


if __name__ == '__main__':
    for page in range(0, 251, 25):
        t = Thread(target=get_date, args=(page,))
        t.start()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值