目录
1.re.match(pattern, string, flags=0模式修正符)
2.re.search(pattern, string, flags=0)
3.re.findall(pattern, string, flags=0)
5.re.split(pattern, string ,maxsplit=0分隔次数,不限制次数,flags=0)
6.re.sub(pattern, repl替换的字符串,也可为一个函数, string, count=0模式匹配后替换的最大次数,默认 0 表示替换所有的匹配,flags=0)
正则表达式
-
正则表达式对象
- group() 返回被re匹配的字符串
- start() 返回匹配开始的位置
- end() 返回匹配结束的位置
- span() 返回一个元组包含匹配 (开始,结束) 的位置
-
正则表达式函数
1.re.match(pattern, string, flags=0模式修正符)
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,返回none;匹配成功,返回第一个匹配的对象。
2.re.search(pattern, string, flags=0)
搜索整个字符串,尝试从字符串的任意位置匹配,并返回第一个成功的匹配。
3.re.findall(pattern, string, flags=0)
搜索整个字符串,返回一个list(所有匹配的对象)
1、当给出的正则表达式带有多个括号时,返回的列表中的元素为多个字符串组成的元组,元组中的元素个数与正则表达式所带的括号数目相同,字符串内容与每个括号内的正则表达式相对应,并且排列的顺序跟括号出现的顺序一样。
2、当给出的正则表达式中带有一个括号时,列表元素为字符串,并与括号中的正则表达式相对应(不是整个正则表达式)。
3、当给出的正则表达式不带括号时,列表元素为字符串,与整个正正则表达式匹配。
分组记法 (?P<name>...)
表达式中的引用记法 (?P=name)
替换时的引用的记法 \g<name>
4.re.compile(pattern,flags=0)
用于编译正则表达式,生成一个正则表达式( Pattern )对象。供 match() 和 search() 这两个函数使用
5.re.split(pattern, string ,maxsplit=0分隔次数,不限制次数,flags=0)
将一个字符串按照正则表达式匹配的结果进行分割,返回列表类型。
6.re.sub(pattern, repl替换的字符串,也可为一个函数, string, count=0模式匹配后替换的最大次数,默认 0 表示替换所有的匹配,flags=0)
在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串。
-
贪婪模式(默认)与懒惰模式
在给出的限定符在后面加上一个问号?即可将贪婪模式转为懒惰模式
xpath
(该部分取自https://cuiqingcai.com/2621.html)
lxml是一款高性能的 Python HTML/XML 解析器
-
表达式
nodename | 选取此节点的所有子节点 |
/ | 从根节点选取,或是元素与元素间的过渡 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
text() | 选取文本 |
-
谓语
谓语用来查找某个特定的节点或者包含某个指定的值的节点。 谓语被嵌在方括号中。
实例 在下面的表格中,列出了带有谓语的一些路径表达式,以及表达式的结果:
/bookstore/book[1]
|
选取属于 bookstore 子元素的第一个 book 元素 |
/bookstore/book[last()]
|
选取属于 bookstore 子元素的最后一个 book 元素 |
/bookstore/book[last()-1]
|
选取属于 bookstore 子元素的倒数第二个 book 元素 |
/bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素 |
//title[@lang=’eng’] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00 |
-
选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
node() | 匹配任何类型的节点 |
-
选取若干路径
通过在路径表达式中使用“|”运算符,可以选取若干个路径。
//book/title | //book/price
|
选取 book 元素的所有 title 和 price 元素 |
//title | //price |
选取文档中的所有 title 和 price 元素。
|
/bookstore/book/title | //price |
选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
-
XPath 运算符
| | 计算两个节点集 |
+,-,* | 加法,减法,乘法 |
div | 除法 |
mod | 计算除法的余数 |
\=,!=,<,<=,>,>= | 等于,不等于,小于,小于或等于,大于,大于或等于 |
or,and | 或,与 |
bs4 BeautifulSoup
(该部分取自 https://www.jianshu.com/p/26a3632796dd)
注意:bs4只能解析html格式的数据
1.把页面数据交给BeautifulSoup处理,生成bs对象
soup = BeautifulSoup(response.text, "html.parser", from_encoding = "...")
soup = BeautifulSoup(response.text, "lxml", from_encoding = "...")
2.从bs对象中查找数据
-
根据标签名查找
soup.a
只能查找得到第一个符合要求的节点,是一个对象
-
获取属性
soup.a.attrs
获取得到所有属性和值,是一个字典
soup.a.attrs['href']
获取指定的属性值soup.a['href']
简写形式
soup.a.get("href")
获取指定的属性值
-
获取文本
soup.a.string
soup.a.text
soup.a.get_text()
[注]如果标签里面还有标签,那么string获取就是空,而后两个获取的是纯文本内容
-
find()方法
返回的是第一个满足条件的标签元素,节点对象
soup.find('a')
查找得到第一个a
soup.find('a', class_='xxx')
查找得到class是xxx的第一个a
soup.find('a', attrs={'class','xxx'})
查找得到第一个class是xxx的a
-
find_all方法
返回的是所有满足条件的标签,一个列表,列表里面都是节点对象
soup.find_all('a')
找到所有a
soup.find_all('a', limit=2)
提取符合要求的前两个a
soup.find_all(['a', 'li'])
查找得到所有的a和li
soup.find_all('a', class_='xxx')
查找得到所有class是xxx的a
soup.find_all('li', class_=re.compile(r'^xiao'))
查找所有的class以xiao开头的li标签
-
select方法
id选择器
#dudu
类选择器
.xixi
标签选择器
div a h1
补充:
str.strip(): 用来去除头尾字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)
str.lstrip():用来去除开头字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)
str.rstrip():用来去除结尾字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)
#爬取51job求职网 保存到数据库
import urllib.request
from bs4 import BeautifulSoup
import time
import pymysql
# 根据url生成请求对象
def handle_request(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}
request = urllib.request.Request(url, headers=headers)
return request
# 解析内容
def parse_content(content, db):
# 生成soup对象
soup = BeautifulSoup(content, 'lxml')
# 先找包含所有工作的div
odivbox = soup.find('div', id='resultList')
# 首先找到包含所有工作的div
odiv_list = odivbox.find_all('div', class_='el')[1:]
# print(len(odiv_list))
for odiv in odiv_list:
# 职位名称
jobname = odiv.select('.t1 > span > a')[0]['title']
# 公司名称
company = odiv.select('.t2 > a')[0]['title']
# 工作地点
area = odiv.select('.t3')[0].string
# 职位月薪
salary = odiv.select('.t4')[0].string
# 发布时间
publish_time = odiv.select('.t5')[0].string
# print(salary, publish_time)
# 保存到字典中
item = {
'职位名称': jobname,
'公司名称': company,
'工作地点': area,
'职位月薪': salary,
'发布时间': publish_time
}
# 保存到文件中
# string = str(item) + '\n'
# fp.write(string)
# 保存到mysql中
save_to_mysql(db, item)
def save_to_mysql(db, item):
# 获取游标
cur = db.cursor()
# 执行sql语句
sql = """insert into work(jobname,company,area,salary,publish_time) values('%s','%s','%s','%s','%s')""" % (item['职位名称'], item['公司名称'], item['工作地点'], item['职位月薪'], item['发布时间'])
# print(sql)
try:
cur.execute(sql)
#提交
db.commit()
except Exception as e:
# print(e)
#错误回滚
db.rollback()
def main():
# fp = open('work.txt', 'w', encoding='utf8')
# 链接数据库
db = pymysql.connect(host="localhost", user="root", password="123456", db="qiangge", port=3306, charset='utf8')
# 用户输入要搜索工作关键字
keyword = input('请输入要搜索的关键字-')
# 用户输入要爬取的起始和结束页码
start_page = int(input('请输入要爬取的起始页码-'))
end_page = int(input('请输入要爬取的结束页码-'))
# 要拼接的起始url
url = 'https://search.51job.com/list/010000,000000,0000,00,9,99,{},2,{}.html'
# 写循环,每一页开始挨着爬取
for page in range(start_page, end_page + 1):
print('正在爬取第%s页......' % page)
# 拼接url
url_page = url.format(keyword, page)
# print(url_page)
# 构建请求对象
request = handle_request(url_page)
# 发送请求,得到响应
content = urllib.request.urlopen(request).read().decode('gbk')
# 解析内容
parse_content(content, db)
print('结束爬取第%s页' % page)
time.sleep(2)
# fp.close()
db.close()
if __name__ == '__main__':
main()