Day6 lxml和多线程

文章目录

  • Day6 lxml和多线程
    • 1. xpath语法
      • 1.1 xpath基本概念
      • 1.2 xml数据格式
      • 1.3 xpath语法
        • 1.3.1 创键树结构获取树的根节点
        • 1.3.2 根据xpath获取指定标签
        • 1.3.3获取标签内容
        • 1.3.4 获取标签属性值
        • 1.3.5 谓语(条件)
        • 1.3.6 通配符
        • 1.3.7 若干路径 —— |
    • 2. 解析某瓣电影
    • 3. 多线程
      • 3.1 基本理论
        • 3.1.1 进程和线程
        • 3.1.2 线程的特点
        • 3.1.3 多线程
        • 3.1.4 多线程原理
      • 3.2 Python使用多线程的方法
    • 4. 多线程解析某瓣电影

1. xpath语法

1.1 xpath基本概念

引入模块

from lxml import etree

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

1.2 xml数据格式

xml和json一样,是一种通过的数据格式(绝大部分编程语言都支持的数据格式)
xml是通过标签(元素)的标签内容和标签属性来保存数据的。

注:先保存一个文件名为data.html的超市信息(模拟网页))

<supermarket name="永辉超市" address="肖家河大厦"><staffs><staff  id="s001"><name>小明</name><position>收营员</position><salary>4000</salary></staff><staff  id="s002"><name>小花</name><position>促销员</position><salary>3500</salary></staff><staff  id="s003"><name>张三</name><position>保洁</position><salary>3000</salary></staff><staff  id="s004"><name>李四</name><position>收营员</position><salary>4000</salary></staff><staff  id="s005"><name>王五</name><position>售货员</position><salary>3800</salary></staff></staffs><goodsList><goods discount="0.9"><name>泡面</name><price>3.5</price><count>120</count></goods><goods><name>火腿肠</name><price>1.5</price><count>332</count></goods><goods><name>矿泉水</name><price>2</price><count>549</count></goods><goods discount="8.5"><name>面包</name><price>5.5</price><count>29</count></goods></goodsList>
</supermarket>

1.3 xpath语法

1.3.1 创键树结构获取树的根节点

# etree.XML(xml数据)
# etree.HTML(html数据)f = open('files/data.xml', encoding='utf-8')
root = etree.XML(f.read())
f.close()

1.3.2 根据xpath获取指定标签

节点对象.xpath(路径) - 返回路径对应的所有的标签,返回值是列表,列表中的元素是标签对象
路径的写法:

a. 绝对路径:用”/“开头的路径 - /标签在树结构中的全路径 (路径必须从根节点开始写)

b. 相对路径:用“.“开头表示当前节点(xpath前面是谁,“.”代表的就是谁,”…“表示当前节点的上层节点

c. 全路径 :用“//”开头的路径 - 在整个数中获取标签

注意:绝对路径和全路径的写法和查找方式和是用谁去点的xpath无关

result = root.xpath('/supermarket/staffs/staff/name/text()')
print(result)  # ['小明', '小花', '张三', '李四', '王五']result = root.xpath('./staffs/staff/name/text()')
print(result)  # ['小明', '小花', '张三', '李四', '王五']# 获取第一个员工对应的staff标签
staff1 = root.xpath('./staffs/staff')[0]            # 获取第一个员工对应的staff标签
result = staff1.xpath('./name/text()')
print(result)       # ['小明']result = staff1.xpath('../staff/name/text()')
print(result)       # ['小明', '小花', '张三', '李四', '王五']result = root.xpath('//name/text()')
print(result)  # ['小明', '小花', '张三', '李四', '王五', '泡面', '火腿肠', '矿泉水', '面包']result = staff1.xpath('//goods/name/text()')
print(result)  # ['泡面', '火腿肠', '矿泉水', '面包']

1.3.3获取标签内容

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

result = root.xpath('//position/text()')
print(result)  # ['收营员', '促销员', '保洁', '收营员', '售货员']

1.3.4 获取标签属性值

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

result = root.xpath('/supermarket/@name')
print(result)    # ['永辉超市']result = root.xpath('//staff/@id')
print(result)  # ['s001', 's002', 's003', 's004', 's005']

1.3.5 谓语(条件)

a. 位置相关谓语

  • [N] - 第N个
  • [last()] - 最后一个
  • [last()-N]; [last()-1] - 倒数第2个 、 [last()-2] - 倒数第3个
  • [position()>N]、[position()<N]、[position()>=N]、[position()<=N] 前几个后几个
result = root.xpath('//staff[1]/name/text()')
print(result)       # ['小明']result = root.xpath('//staff[last()]/name/text()')
print(result)       # ['王五']result = root.xpath('//staff[last()-1]/name/text()')
print(result)       # ['李四']result = root.xpath('//staff[position()<3]/name/text()')
print(result)   # ['小明', '小花']

b.属性相关谓语

  • [@属性名=属性值] - 指定属性是指定值的标签
  • [@属性名] - 拥有指定属性的标签
# staff[@class="c1"] == staff.c1
result = root.xpath('//staff[@class="c1"]/name/text()')
print(result)   # [] (没有class值为c1的,所有为空)result = root.xpath('//staff[@id="s003"]/name/text()')
print(result)  # ['张三']result = root.xpath('//goods[@discount]/name/text()')
print(result)  # ['泡面', '面包']

c.子标签内容相关谓语
根据子标签的内容来筛选标签

  • [子标签名>数据]
  • [子标签名<数据]
  • [子标签名>=数据]
  • [子标签名<=数据]
  • [子标签名=数据]
result = root.xpath('//goods[price=2]/name/text()')
print(result)  # ['矿泉水']

1.3.6 通配符

写路径的时候用*来表示所有标签或者所有属性

result = root.xpath('//staff[1]/*/text()')
print(result)  # ['小明', '收营员', '4000']# *[@class="c1"]  == .c1
result = root.xpath('//*[@class="c1"]/name/text()')
print(result)  # []result = root.xpath('//goods[@*]/name/text()')
print(result)  # ['泡面', '面包']result = root.xpath('/supermarket/@*')
print(result)  # ['永辉超市', '肖家河大厦']

1.3.7 若干路径 —— |

路径1|路径2 —— 同时获取路径1和路径2的内容

result = root.xpath('//goods/name/text()|//staff/position/text()')
print(result)  # ['收营员', '促销员', '保洁', '收营员', '售货员', '泡面', '火腿肠', '矿泉水', '面包']

2. 解析某瓣电影

'''
Author:KathAmy
Date:2022/8/18  11:45
键盘敲烂,共同进步!
'''
import requests
import csv
from lxml import etreedef get_net_data():url = 'https://movie.douban.com/top250'Headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.81 Safari/537.36 Edg/104.0.1293.47'}response = requests.get(url, headers=Headers)return response.textdef analysis_data(html: str):root = etree.HTML(html)names = root.xpath('//ol[@class="grid_view"]/li/div/div[@class="info"]/div[1]/a/span[1]/text()')# print(names)  测试一下scores = root.xpath('//ol[@class="grid_view"]/li/div/div[@class="info"]/div[2]/div/span[2]/text()')# print(scores)comment_count = root.xpath('//ol[@class="grid_view"]/li/div/div[@class="info"]/div[2]/div/span[last()]/text()')# print(comment_count)slogan = root.xpath('//ol[@class="grid_view"]/li/div/div[@class="info"]/div[2]/p[@class="quote"]/span/text()')# print(slogan)all_data = list(map(lambda i1, i2, i3, i4: [i1, i2, i3, i4], names, scores, comment_count, slogan))with open('电影.csv', 'w', encoding='utf-8', newline='') as f:writer = csv.writer(f)writer.writerow(['电影名', '评分', '评论数', '标语'])writer.writerows(all_data)def analysis_data2(html: str):root = etree.HTML(html)all_film_div = root.xpath('//ol[@class="grid_view"]/li/div')all_data = []for div in all_film_div:names = div.xpath('./div[@class="info"]/div[1]/a/span[1]/text()')[0]scores = div.xpath('./div[@class="info"]/div[2]/div/span[2]/text()')[0]comment_count = div.xpath('./div[@class="info"]/div[2]/div/span[last()]/text()')[0]slogan = div.xpath('./div[@class="info"]/div[2]/p[@class="quote"]/span/text()')[0]all_data.append([names, scores, comment_count, slogan])# print(all_data)# print('-----------------------------------华丽的分割线-----------------------------------')with open('电影2.csv', 'w', encoding='utf-8', newline='') as f:writer = csv.writer(f)writer.writerow(['电影名', '评分', '评论数', '标语'])writer.writerows(all_data)if __name__ == '__main__':data = get_net_data()analysis_data2(data)

3. 多线程

3.1 基本理论

3.1.1 进程和线程

进程: 一个正在运行的应用程序就是一个进程,每个进程均运行在其专门且受保护的内存空间中
线程: 线程是进程执行人物的基本单元(一个进程中的人物都是在线程中执行的)

进程就是车间,线程就是车间里面的工人。
一个进程中默认有一个线程,这个线程叫主线程。

3.1.2 线程的特点

如果在一个线程中执行多个任务,任务是串行执行的。
(当一个程序中有很多个任务的时候,如果只有一个线程,那么程序执行的效率比较低)

3.1.3 多线程

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

3.1.4 多线程原理

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

3.2 Python使用多线程的方法

一个进程默认只有一个线程,这个线程叫主线程,主线程以外的线程都叫子线程。
Python程序中如果需要子线程,必须创建线程类(Thread)的对象。

from threading import Thread
from time import sleep
from datetime import datetimedef download(name):print(f'{name}开始下载:{datetime.now()}')sleep(2)print(f'{name}下载结束:{datetime.now()}')if __name__ == '__main__':# 情况1:在一个线程(主线程)中下载3个电影download('肖生克的救赎')download('霸王别姬')download('阿甘正传')# 情况2:使用3个子线程分别下载3个电影# 1)创建线程对象'''线程对象 = Thread(target=函数, args=元组)  target - 目标  args - 参数a.函数  -  可以是普通函数函数名,也可以是匿名函数。这个函数就是需要在子线程中执行的任务。b.元组  -  元组中的元素就是在子线程中调用target对应的函数的时候对应的参数'''t1 = Thread(target=download, args=('肖生克的救赎',))t2 = Thread(target=download, args=('霸王别姬',))t3 = Thread(target=download, args=('阿甘正传',))# 2)启动线程  -  让子线程调用对应的函数t1.start()t2.start()t3.start()

4. 多线程解析某瓣电影

'''
Author:KathAmy
Date:2022/8/18  19:22
键盘敲烂,共同进步!
'''
import requests
from datetime import datetime
from threading import Thread
import csv
from lxml import etree
from bs4 import BeautifulSoupHeaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.81 Safari/537.36 Edg/104.0.1293.47'}def get_one_page_data(page):print(f'第{page}页开始获取:{datetime.now()}')url = fr'https://movie.douban.com/top250?start={page}&filter='response = requests.get(url, headers=Headers)print('下载完成!')print(f'第{page}页开始获取:{datetime.now()}')def analysis_data(html: str):soup = BeautifulSoup(html, 'lxml')all_film_div = soup.select('.grid_view>li>.item')  # 返回的是一个列表all_film = []for div in all_film_div:name = div.select_one('.title').textscore = div.select_one('.rating_num').textinfo = div.select_one('.bd>p').text.strip().split('\n')[-1].strip()# time, country, category = info.split('/')info_list = info.split('/')time = info_list[0]  # 避免格式不统一,集体切割就OKcountry = info_list[-2]  # 避免格式不统一,集体切割就OKcategory = info_list[-1]  # 避免格式不统一,集体切割就OKslogan = div.select_one('.inq')if slogan:slogan = slogan.textelse:slogan = ''comment = div.select('.star>span')[-1].text[:-3]print(name)print(score)print(time, country, category)print(slogan)print(comment)print('-----------------------------------华丽的分割线-----------------------------------')# all_film.append([name, score, time.strip(), country.strip(), category.strip(), slogan, comment])# with open('电影3.csv', 'w', encoding='utf-8', newline='') as f:#     writer = csv.writer(f)#     writer.writerow(['电影名', '评分', '上映时间', '国家', '类型', '标语', '评论人数'])#     writer.writerows(all_film)if __name__ == '__main__':for page in range(0, 256, 25):t = Thread(target=get_one_page_data, args=(page,))t.start()

Python Day6 爬虫-lxml和多线程相关推荐

  1. python网络爬虫系列教程——python中lxml库应用全解(xpath表达式)

    全栈工程师开发手册 (作者:栾鹏) python教程全解 python网络爬虫lxml库的应用全解. 在线安装方法:cmd中输入"pip install lxml" 离线安装,下载 ...

  2. python网络爬虫系列教程——python中pyquery库应用全解

    全栈工程师开发手册 (作者:栾鹏) python教程全解 python网络爬虫lxml库的应用全解. 在线安装方法:cmd中输入"pip install pyquery" 离线安装 ...

  3. python写爬虫4-多线程爬虫(采集58出租房信息)_python实现多线程爬虫

    前言: 本文利用python语言实现了一个多线程爬虫. 正文: 开发环境: ubuntu16.04,python3.6,bs4,virtualenv(虚拟环境) 创建虚拟环境: 创建项目文件夹,并为项 ...

  4. python爬虫实战之多线程爬取前程无忧简历

    python爬虫实战之多线程爬取前程无忧简历 import requests import re import threading import time from queue import Queu ...

  5. python爬虫第二弹-多线程爬取网站歌曲

    python爬虫第二弹-多线程爬取网站歌曲 一.简介 二.使用的环境 三.网页解析 1.获取网页的最大页数 2.获取每一页的url形式 3.获取每首歌曲的相关信息 4.获取下载的链接 四.代码实现 一 ...

  6. 并发编程(五)python实现生产者消费者模式多线程爬虫

    并发编程专栏系列博客 并发编程(一)python并发编程简介 并发编程(二)怎样选择多线程多进程和多协程 并发编程(三)Python编程慢的罪魁祸首.全局解释器锁GIL 并发编程(四)如何使用多线程, ...

  7. UN Comtrade python爬虫实现,多线程动态ip

    原帖见[爬虫]Python使用动态IP,多线程,爬取uncomtrade的数据_学金融的程序员懒羊羊的博客-CSDN博客_爬虫动态ip 修改了url代码,自定义函数的递归问题,跑通代码. 需要自己去i ...

  8. Python多线程爬虫,小米应用商城app信息爬虫程序,多线程和多进程两种实现思路

    目录 小米应用商城app信息爬虫程序 1.需求分析 2.url分析 3.程序设计思路 4.程序代码 5.程序优化与升级 小米应用商城app信息爬虫程序 1.需求分析 看到小米应用的首页:http:// ...

  9. 爬取妹子图(python):爬虫(bs+rq)+ gevent多线程

    爬取妹子图(python):爬虫(bs+rq)+ gevent多线程 简介 我观察爬取妹子图算是爬虫专业户必做的事情之一,所以我也做了一个,结果是有3.45GB,49847张图. 打算依靠这个图库做个 ...

最新文章

  1. 启用IIS的Gzip压缩 【转】
  2. volatile和final
  3. Android通过adb命令传参给APP的方法
  4. bzoj2132: 圈地计划
  5. android jni 调用java对象_Android NDK开发之Jni调用Java对象
  6. python课程索引-0222
  7. Zookeeper 如何选举master 主节点?
  8. python numpy 函数详解_numpy.linspace函数具体使用详解
  9. 安装无奈7和Linux,linux7安装teamViewer
  10. css半透明渐变过渡效果
  11. JarvisOJ 逆向Writeup
  12. 经典的测试开发面试题
  13. 域名注册必须实名认证 《互联网域名管理办法》11月1日实施
  14. 五大电子邮件的营销方法,教你提高客户的回头率!
  15. JAVA图书管理系统不用数据库_java简单的图书管理系统(只用java代码不用数据库和可视化界面,一个管理员表和图书表)...
  16. 服务器与客户端的TCP连接
  17. 【Windows】win10多桌面与多任务
  18. c语言和Python整除符号,互联网常识:python除法运算符有哪些
  19. mysql忘记密码找回root密码
  20. 怎样记住英语单词的意思

热门文章

  1. 面试题:设计模式记不住,来看看怎么办?
  2. 计算机在家电中的用途,计算机技术在信家电中的运用11.doc
  3. 【2019暑假集训】07.05比赛总结
  4. 过去的事情就让他停留在过去吧
  5. linux clocksource
  6. 菜鸟学习网安写的笔记---1
  7. 在word2013中加载endnote
  8. 科技型中小企业税收优惠政策
  9. bzoj4872 分手是祝愿
  10. 解决 微信、QQ、微博、支付宝 第三方登录 不同应用间用户共享的问题