bs4:BeautifulSoup
作用:用來解析網(wǎng)頁系任,提取指定數(shù)據(jù)的罢低。提供的接口非常簡單说墨。使用起來人性化璃饱。所以用的比較多与斤,但是bs4只能解析html格式的數(shù)據(jù)
安裝:
pip install bs4
bs4簡單使用
整體使用步驟:
bs4里面有一個類,BeautifulSoup,然后通過這個類將網(wǎng)頁html格式字符串生成一個對象撩穿,然后通過對象的方法來進行查找指定元素
(1)將本地html文件轉(zhuǎn)化為對象
soup = BeautifulSoup(open('soup.html', encoding='utf8'), 'lxml')
lxml :
是一個文件解析庫磷支,通過它的解析生成對象,是一個第三方庫食寡,需要安裝雾狈,
安裝
pip install lxml
html.parser :
是python自帶的一個文件解析庫
eg:
soup = BeautifulSoup(open('soup.html', encoding='utf8'), 'lxml')
根據(jù)標簽名查找
soup.a
只能查找得到第一個符合要求的節(jié)點,是一個對象,bs4自己封裝類的對象
獲取屬性
soup.a.attrs
獲取得到所有屬性和值抵皱,是一個字典
soup.a.attrs['href']
獲取指定的屬性值
soup.a['href']
簡寫形式
獲取文本
soup.a.string
soup.a.text
soup.a.get_text()
[注]如果標簽里面還有標簽善榛,那么string獲取就是空,而后兩個獲取的是純文本內(nèi)容
find_all方法
返回的是一個列表叨叙,列表里面都是節(jié)點對象
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
eg :
div #dudu .xixi a
空格:代表后面的節(jié)點是前面節(jié)點的子節(jié)點或者子孫節(jié)點
div > #dudu > a > .xixi
: 代表后面的節(jié)點是前面節(jié)點的子節(jié)點
返回的是一個列表锭弊,列表里面都是符合要求的節(jié)點對象
普通對象也能調(diào)用select方法,查找的是這個對象下面的內(nèi)容
實例
爬取三國演義小說保存到文件
import urllib.request
from bs4 import BeautifulSoup
import time
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, fp):
# 生成soup對象
soup = BeautifulSoup(content, 'lxml')
# 查找所有的章節(jié)鏈接和標題內(nèi)容
oa_list = soup.select('.book-mulu > ul > li > a')
# print(len(oa_list))
# 遍歷列表擂错,依次獲取每一個鏈接和內(nèi)容
for oa in oa_list:
# 獲取鏈接
+ oa['href']
# 獲取標題
title = oa.string
print('正在下載--%s--......' % title)
# 獲取章節(jié)內(nèi)容函數(shù)
text = get_text(href)
# 寫入文件
fp.write(title + '\n' + text)
print('結(jié)束下載--%s--' % title)
time.sleep(2)
# 提取得到章節(jié)內(nèi)容
def get_text(href):
# 構(gòu)建請求對象
request = handle_request(href)
content = urllib.request.urlopen(request).read().decode('utf8')
# 生成soup對象
soup = BeautifulSoup(content, 'lxml')
# 查找包含內(nèi)容的div
odiv = soup.find('div', class_='chapter_content')
return odiv.text
def main():
# 打開文件
fp = open('三國演義.txt', 'w', encoding='utf8')
url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
# 構(gòu)建請求對象
request = handle_request(url)
# 發(fā)送請求味滞,得到響應(yīng)
content = urllib.request.urlopen(request).read().decode('utf8')
# 解析內(nèi)容即可
parse_content(content, fp)
fp.close()
if __name__ == '__main__':
main()
爬取51job求職網(wǎng) 保存到數(shù)據(jù)庫
import urllib.request
from bs4 import BeautifulSoup
import time
import pymysql
# 根據(jù)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
# 解析內(nèi)容
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
# 發(fā)布時間
publish_time = odiv.select('.t5')[0].string
# print(salary, publish_time)
# 保存到字典中
item = {
'職位名稱': jobname,
'公司名稱': company,
'工作地點': area,
'職位月薪': salary,
'發(fā)布時間': publish_time
}
# 保存到文件中
# string = str(item) + '\n'
# fp.write(string)
# 保存到mysql中
save_to_mysql(db, item)
def save_to_mysql(db, item):
# 獲取游標
cur = db.cursor()
# 執(zhí)行sql語句
sql = """insert into work(jobname,company,area,salary,publish_time) values('%s','%s','%s','%s','%s')""" % (item['職位名稱'], item['公司名稱'], item['工作地點'], item['職位月薪'], item['發(fā)布時間'])
# 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')
# 鏈接數(shù)據(jù)庫
db = pymysql.connect(host="localhost", user="root", password="123456", db="qiangge", port=3306, charset='utf8')
# 用戶輸入要搜索工作關(guān)鍵字
keyword = input('請輸入要搜索的關(guān)鍵字-')
# 用戶輸入要爬取的起始和結(jié)束頁碼
start_page = int(input('請輸入要爬取的起始頁碼-'))
end_page = int(input('請輸入要爬取的結(jié)束頁碼-'))
# 要拼接的起始url
url = 'https://search.51job.com/list/010000,000000,0000,00,9,99,{},2,{}.html'
# 寫循環(huán),每一頁開始挨著爬取
for page in range(start_page, end_page + 1):
print('正在爬取第%s頁......' % page)
# 拼接url
url_page = url.format(keyword, page)
# print(url_page)
# 構(gòu)建請求對象
request = handle_request(url_page)
# 發(fā)送請求钮呀,得到響應(yīng)
content = urllib.request.urlopen(request).read().decode('gbk')
# 解析內(nèi)容
parse_content(content, db)
print('結(jié)束爬取第%s頁' % page)
time.sleep(2)
# fp.close()
db.close()
if __name__ == '__main__':
main()