一、基础知识
1、获取用户输入的内容可通过 input函数:url = input("请输入要爬取的网页url:")
2、字典遍历 for key in 字典:
3、创建文件夹 使用os模块中的 os.mkdir()
4、路径拼接:os.path.join("path1,"path2")
5、文件是否存在 os.path.exists(path)
6、enumerate函数:将可遍历的对象(列表,字典,元组,字符串)组合成一个索引序列,同时给出数据下标和数据
7、字符串格式化: %+格式指定符:(print('%s,今年%d岁' %(name,age))) format()函数:(print('{},今年{}岁'.format(name,age))) f-string:(print(f'{name},今年{age}岁'))
二、发送请求
1.1 使用request模块发送请求,
使用方法:第一步导入该模块 import requests 第二步:使用requests类即可
简单示例如下:
resp = requests.get(url="https://www.baidu.com",params=params,headers=headers,cookies=cookies)
获取文本内容:resp.text
获取二进制内容:resp.content
指定响应的字符格式:resp.encoding='utf-8'
获取响应字符格式:resp.encoding
获取请求的Url:resp.url
获取响应状态码:resp.status_code
如果响应数据是json格式可将相应参数直接转成json格式:resp.json()
1.2 url的解析
1、url的解析使用urllib模块:rllib是一个url模块包,主 urllib.request:打开和读取url urllib.error:异常模块 urllib.parse:解析url urllib.robotparser:解析robots.txt文件
2、解析url:使用urllib中的parse模块:quote()编码 unquote()解码
3、下载图片并保存到指定路径:使用urllib模块中的request: request.urlretrieve()
三、数据的解析:
2.1 xpath进行解析
详情可参考:XPath 教程 (w3school.com.cn)
2.1.1常用表达式
1、nodename:获取该节点名称下的所有子节点
2、/:从根节点获取 3、//:从匹配选择的当前节点选择文档中的节点,而不考虑他们的位置
4、.:选取当前节点 5、..:选取当前节点的父节点 6、@:选取属性
2.2.2 谓语
查找某个特定的节点或者包含某个某个指定值的节点,被嵌在方括号中
例如: 选择属性id值为content的div节点: //div[@id='content']
2.2.3 常用案例实例
实例:
```
html="""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<div id="content">
<ul id="u1">
<li>北京</li>
<li>上海</li>
<li>河南</li>
<li>郑州</li>
<li>北京</li>
</ul>
<ul id="u2">
<li>open</li>
<li>two</li>
</ul>
</div>
<div id="url">
<a href="http://www.58.com" title="58">58</a>
<a href="http://www.csdn.net" title="CSDN">csdn</a>
<ul>
<li>北京</li>
</ul>
</div>
<table id="content"></table>
</body>
</html>"""
全局(节点)搜索://nodename
选择属性id值为content的div节点: //div[@id='content']
查询含有id属性的所有元素: //*[@id]
获取 div中的 id属性的值://div/@id
根据文本内容查找元素 text() 或者 string()
当前元素下搜索文本内容是北京的li标签:.//li[text()="北京"]'
函数://div[last()] 选取最后一个div元素 last()-num 选取倒数第几个元素
//div[contains(@id,"cont")] 选取id属性包含cont的div元素
2.2.4 如何解析html/xml
使用lxml: lxml是一个 html/xml解析器,主要功能是提取和解析html/xml数据,安装 pip install lxml
第一步:导入 lxml模块 from lxml import etree
第二步: selector = etree.HTML(html)
第三步:selector.xpath(xpath语法内容)
四、文件操作
使用open函数
示例如下:读取一个文件为例
# file:文件名,mode:模式 "r","w" "a(追加写入)","x(创建一个新文件并写入)","b(二字节模式)",encoding:编码格式,newline="\r" 指定换行符:"\r" "\n" "\r\n"
with open(file="demo.html",mode="r",encoding="utf-8") as fp:
# ct = fp.read();#读取全部内容
# ct1 = fp.readline();#一行一行的读取
# fp.write()写入
ct2 = fp.readable()# 是否可读
fp.close()
五、excel操作
5.1 操作csv
csv是python内置的模块无需安装 文档地址:csv --- CSV 文件读写 — Python 3.12.0 文档 写入步骤如下:
1、导入:import csv;2、创建writer对象:writer = csv.writer(file);3、通过writerow()或者writerows()函数写入
案例如下:
#默认是两倍行距,可通过newline=''改成一倍行距
with open('student.csv','a+',newline='') as file:
# #创建writer对象
writer = csv.writer(file)
# #写入一条数据
#writer.writerow(['王五',29])
# #写入多条数据
lst = [
['石六',23],
['九州',24]
]
writer.writerows(lst),
读取步骤如下: 1、创建reader对象:reader = csv.reader(file);2、遍历该reader对象,获取到的每条数据都是一个列表
案例如下:
with open('student.csv','r',newline='') as file:
reader = csv.reader(file)
for row in reader:
print(row)
5.2 操作excel
操作excel选用的是openpyxl模块,模块安装:pip install openpyxl 文档地址:教程 — openpyxl 3.0.7 文档 (openpyxl-chinese-docs.readthedocs.io)
读取excel案例如下:
#加载excel文件
wb = openpyxl.load_workbook('test.xlsx')
#只有一个工作簿时
sheet = wb.active
#多个时可以通过wb[sheetName]
#获取指定单元格中的值
cell = sheet['A1']
print(cell.value)
print("----")
#获取某一列的值
row = sheet['A']
#遍历某一列中的所有单元格
for cell in row:
print(cell.value)#获取单元格中的值
print("---")
#获取某一行索引从1开始
column = sheet[1]
#遍历某一行行中的单元格
for cell in column:
print(cell.value)
print('##')
#获取前两行的数据
column = sheet[1:2]
#遍历每一行
for row in column:
#遍历每一行中的单元格
for cell in row:
print(cell.value)
print('$$$$')
#获取前两列中的值
column = sheet['A':'B']
#遍历每一列
for row in column:
#遍历每一列中的单元格
for cell in row:
print(cell.value)
写入excel案例:
import openpyxl
#创建工作簿对象
workbook = openpyxl.Workbook()
#获取工作簿
sheet = workbook.active
#获取指定单元格
cell = sheet['A1']
#向单元格中写入数据
cell.value='中国美丽乡村'
#写入一行数据
lst = ['姓名','年龄','性别']
sheet.append(lst)
#保存
workbook.save('test.xlsx')
六、BeautifulSoap
是一个可以从HTML/XML中提取数据的另一个python库,功能简单而强大。安装方式 pip install bs4 使用方式: from bs4 import BeautifulSoup
使用案例
# 使用标准库解析器
#bs = BeautifulSoup(html,"html.parser")
#使用lxml解析器
bs = BeautifulSoup(html,"lxml")
#常用方法
#获取满足要求的首个标签 find(标签名,属性)
print(bs.find('div',id='content1'))
print(bs.find('a',class_='t1'))
print(bs.find('a',attrs={'title':'58'}))
#获取满足要求所有标签 find_all(标签名,属性)
print(bs.find_all('div',id='url'))
#css选择器 select,同级之间没有空格,不同级之间使用空格
#通过id查找
print(bs.select('#url'))
#通过class查找
print(bs.select(".t1"))
#通过属性查找
print(bs.select('a[title="CSDN"]'))
#通过标签对象查找
#获取某个元素
print(bs.div)
#获取标签的属性 attrs
print(bs.div.attrs)
#获取单个属性
print(bs.div.get('id'))
print(bs.div['id'])
#获取文本内容
print(bs.li.text)
print(bs.li.string)
七、多线程
7.1多线程使用python中的内置模块threading
主要是该模块中的Thread类即threading.Thread类
简单使用案例:
#多线程的简单使用
def multi():
t1 = threading.Thread(target=fun1)
t2 = threading.Thread(target=fun2)
t1.start()
t2.start()
'''
继承实现多线程类
继承 threading.Thread类
实现run()方法
调用Thread类的run()方法
'''
class ThreadDemo1(threading.Thread):
def run(self):
for i in range(5):
print("fun1中的值为:", i)
time.sleep(1) # 睡眠1s
t1 = threading.current_thread()#获取当前线程对象
threading.enumerate() #获取N多线程对象信息
t1.getName()#获取线程名称
t1.setName()#修改线程名称
7.2 线程安全队列queue
该类也是Python内置模块,使用方式 from queue import Queue
八、动态网页爬虫
网站不重新加载,通过ajax技术动态更新部分数据 动态网页爬虫解决方案:1、直接分析ajax调用的接口 2、使用selenium+chromdriver模拟浏览器行为获取数据(代码量多,性能低) 安装:pip install selenium,
chromdriver插件安装在python解释器的安装路径下,chromdriver版本与chrom的版本有关,地址:chromedriver.storage.googleapis.com/index.html 119及以上的googlechromelabs.github.io/chrome-for-… 查看chrom和chromdriver版本号:
8.1 浏览器的简单操作:
# 构造浏览器
driver = webdriver.Chrome()
#driver.get("http://www.baidu.com")
str1 = driver.capabilities['browserVersion'] #查看chrome版本
str2 = driver.capabilities['chrome']['chromedriverVersion'].split(' ')[0] #查看python下的chromedriver版本
print(str1)
print(str2)
浏览器常用操作
# 获取网页源代码
#driver.page_source
#截图
#driver.save_screenshot()
#关闭当前页
#driver.close()
#关闭浏览器
#driver.quit()
在selenium4.7.2版本上运行会闪退,解决方案降低selenium版本,例如降为4.4.3
8.2 selenium定位元素
'''
旧版本: element后加s可以获取全部满足条件的元素
find_element_by_id()通过id定位元素
find_element_by_name()通过name属性定位元素
find_element_by_class_name()通过className定位元素
find_element_by_tag_name()通过标签名称定位元素
find_element_by_css_selector()通过css样式定位元素
find_element_by_link_text()通过连接文本定位元素
find_element_by_xpath()通过xpath语法定位元素
新版本4.0以后
input = driver.find_element(By.ID,"kw")
'''
input = driver.find_element(By.ID,"kw")
#在文本框中输入内容
input.send_keys("python")
8.3 操作表单元素
操作表单元素: 输入框: 使用 send_keys(value)函数
复选框和按钮:使用click()函数
下拉列表框:创建Select对象
'''
driver.get("http://www.baidu.com")
input = driver.find_element(By.ID,"kw")
#在文本框中输入内容
input.send_keys("python")
#下拉类表框,创建select对象
driver.get("https://kyfw.12306.cn/otn/regist/init")
select = Select(driver.find_element(By.ID,"cardType"))
#根据索引获取
select.select_by_index(1)
#根据value获取
select.select_by_value("B")
#根据可见文本
select.select_by_visible_text("台湾居民来往大陆证")
8.4 selenium行为链
selenium的行为链:网站有时会做一些验证行为来判断是否是人类
使用方式即步骤
导入:from selenium.webdriver.common.action_chains import ActionChains
步骤:
driver.get("https://cn.bing.com/")
#创建对象
actions = ActionChains(driver)
# #移动到某个元素
# actions.move_to_element(element)
# #文本框填入内容
# actions.send_keys_to_element(element,'python')
# #单击
# actions.click(element)
....
#执行行为链
actions.perform()
案例:
driver.get("https://www.baidu.com/")
#获取元素
input_element = driver.find_element(By.ID,"kw")
button_ele = driver.find_element(By.ID,"su")
#创建对象
actions = ActionChains(driver)
# #移动到文本框,并输入元素
actions.move_to_element(input_element)
actions.send_keys_to_element(input_element,'python')
#移动到搜索按钮上并单击
actions.move_to_element(button_ele)
actions.click(button_ele)
#执行行为链
actions.perform()
8.5 selenium操作cookie
案例:
driver.get("https://www.baidu.com/")
#获取所有cookie
driver.get_cookies()
#获取指定cookie
driver.get_cookie("BAIDUID")
#添加cookie
driver.add_cookie({"name":"test","value":"123"})
dd = driver.get_cookie("test")
print(dd)
#删除cookie
driver.delete_cookie("test")
print("---")
dd = driver.get_cookie("test")
print(dd)
8.6 selenium页面等待
有些页面中的元素不是立即出现的,而是由其他请求填充到页面,此时就用到了页面中的等待,等待分为隐式等待和显示等待两种
案例
使用方式:1、导入以下块(显示等待时):
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By
2、编写代码:
隐式等待:
#隐式等待5s钟后查找id为abc的元素
driver.get("https://www.baidu.com/")
driver.implicitly_wait(5)
driver.find_element(By.ID,"abc")
显示等待:
driver.get("https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=wf")
#等待100s
WebDriverWait(driver,100).until(
#条件,输入框中的出发地为北京
ec.text_to_be_present_in_element_value((By.ID,'fromStationText'),'北京')
)
#等待100s
WebDriverWait(driver,100).until(
#条件,输入框中的目的地为上海
ec.text_to_be_present_in_element_value((By.ID,'toStationText'),'上海')
)
#满足以上两个条件触发查询
btn = driver.find_element(By.ID,"query_ticket")
btn.click()待:
8.7 字体反爬
字体反爬:开发者创建的自定义字体,网页中的内容为字体代码而不是字体本身,需要进行解码
网页开发者通常会将字体编码成base64方式,因此我们可以在网页中找到@font_face属性,然后用Python解析该base64
或者通过@font-face属性中的url去动态加载
关于@font-face属性的介绍:https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face
分析字体将字体转换成xml文件,然后查看其中的cmap和glyf属性,其中cmap存储的是code和name的映射,而glyf存储的是每个name下的字体绘制规则
安装 fontTools模块:pip install fontTools
可通过fontcreator软件去解析自定义字体