find相关方法
find_parents() 搜索所有父亲
find_parrent() 搜索单个父亲
find_next_siblings()搜索所有兄弟
find_next_sibling()搜索单个兄弟
find_previous_siblings() 往上搜索所有兄弟
find_previous_sibling() 往上搜索单个兄弟
find_all_next() 往下搜索所有元素
find_next()往下查找单个元素
搜索树
- 字符串过滤器
- 正则表达式过滤器
我们用正则表达式里面compile方法编译一个正则表达式传给 find 或者 findall这个方法可以实现一个正则表达式的一个过滤器的搜索 - 列表过滤器
- True过滤器
- 方法过滤器
修改文档树
- 修改tag的名称和属性
- 修改string 属性赋值,就相当于用当前的内容替代了原来的内容
- append() 像tag中添加内容,就好像Python的列表的 .append() 方法
- decompose() 修改删除段落,对于一些没有必要的文章段落我们可以给他删除掉
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc, features="lxml")
# 修改tag的名称和属性
tag_p = soup.p
print(tag_p)
tag_p.name = 'w' # 修改标签的名称
tag_p['class'] = 'age' # 修改属性
print(tag_p)
# 修改string值
print(tag_p.string)
tag_p.string = 'you need python'
print(tag_p.string)
# append添加值
tag_p.append('abc')
print(tag_p)
# 删除
r = soup.find(class_='title')
# print(r)
r.decompose()
print(soup)
bs4-select()方法简单应用案例
from bs4 import BeautifulSoup
html = """
<table class="tablelist" cellpadding="0" cellspacing="0">
<tbody>
<tr class="h">
<td class="l" width="374">职位名称</td>
<td>职位类别</td>
<td>人数</td>
<td>地点</td>
<td>发布时间</td>
</tr>
<tr class="even">
<td class="l square"><a target="_blank" href="position_detail.php?id=33824&keywords=python&tid=87&lid=2218">22989-金融云区块链高级研发工程师(深圳)</a></td>
<td>技术类</td>
<td>1</td>
<td>深圳</td>
<td>2017-11-25</td>
</tr>
<tr class="odd">
<td class="l square"><a target="_blank" href="position_detail.php?id=29938&keywords=python&tid=87&lid=2218">22989-金融云高级后台开发</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2017-11-25</td>
</tr>
<tr class="even">
<td class="l square"><a target="_blank" href="position_detail.php?id=31236&keywords=python&tid=87&lid=2218">SNG16-腾讯音乐运营开发工程师(深圳)</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2017-11-25</td>
</tr>
<tr class="odd">
<td class="l square"><a target="_blank" href="position_detail.php?id=31235&keywords=python&tid=87&lid=2218">SNG16-腾讯音乐业务运维工程师(深圳)</a></td>
<td>技术类</td>
<td>1</td>
<td>深圳</td>
<td>2017-11-25</td>
</tr>
<tr class="even">
<td class="l square"><a target="_blank" href="position_detail.php?id=34531&keywords=python&tid=87&lid=2218">TEG03-高级研发工程师(深圳)</a></td>
<td>技术类</td>
<td>1</td>
<td>深圳</td>
<td>2017-11-24</td>
</tr>
<tr class="odd">
<td class="l square"><a target="_blank" href="position_detail.php?id=34532&keywords=python&tid=87&lid=2218">TEG03-高级图像算法研发工程师(深圳)</a></td>
<td>技术类</td>
<td>1</td>
<td>深圳</td>
<td>2017-11-24</td>
</tr>
<tr class="even">
<td class="l square"><a target="_blank" href="position_detail.php?id=31648&keywords=python&tid=87&lid=2218">TEG11-高级AI开发工程师(深圳)</a></td>
<td>技术类</td>
<td>4</td>
<td>深圳</td>
<td>2017-11-24</td>
</tr>
<tr class="odd">
<td class="l square"><a target="_blank" href="position_detail.php?id=32218&keywords=python&tid=87&lid=2218">15851-后台开发工程师</a></td>
<td>技术类</td>
<td>1</td>
<td>深圳</td>
<td>2017-11-24</td>
</tr>
<tr class="even">
<td class="l square"><a target="_blank" href="position_detail.php?id=32217&keywords=python&tid=87&lid=2218">15851-后台开发工程师</a></td>
<td>技术类</td>
<td>1</td>
<td>深圳</td>
<td>2017-11-24</td>
</tr>
<tr class="odd">
<td class="l square"><a id="test" class="test" target='_blank' href="position_detail.php?id=34511&keywords=python&tid=87&lid=2218">SNG11-高级业务运维工程师(深圳)</a></td>
<td>技术类</td>
<td>1</td>
<td>深圳</td>
<td>2017-11-24</td>
</tr>
</tbody>
</table>
"""
soup = BeautifulSoup(html, 'lxml')
# 1获取所有的tr
trs = soup.select('tr')
print(trs)
# 2 获取第二个tr标签
tr = soup.select('tr')[1]
print(tr)
# 3 获取所有class等于even的tr标签
tr = soup.select('.even')
# print(tr)
# 4 获取所有a标签的href属性
a_lst = soup.select('a')
for a in a_lst:
href = a['href']
print(href)
# 5 获取职位信息
trs = soup.select('tr')[1:]
for tr in trs:
info = list(tr.stripped_strings)[0]
print(info)
fake_useragent
多次使用一个User-Agent爬取同一网站可能触发相应反爬机制,用fake_useragent模块频繁更换UserAgent,该模块需要安装:
pip install -i https://pypi.douban.com/simple/ fake_useragent
应用:
import requests
from fake_useragent import UserAgent
headers= {'User-Agent':str(UserAgent().random)}
r = requests.get(url, proxies=proxies, headers=headers, timeout=10)
用bs4提取各城市天气数据
# 需求:获取全中国所有的城市名字以及对应的温度保存到csv文件当中
# http://www.weather.com.cn/textFC/hb.shtml 华北
import requests
from bs4 import BeautifulSoup
import csv
import random
titles = ('city', 'temp')
# 定义一个函数来解析网页
def parse_page(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/86.0.4240.75 Safari/537.36 '
}
response = requests.get(url, headers=headers)
# print(response.content.decode('utf-8'))
html = response.content.decode('utf-8')
# pip install html5lib
soup = BeautifulSoup(html, 'html5lib')
# 先获取class="conMidtab"
conMidtab = soup.find('div', class_='conMidtab')
# 获取所有的table标签
tables = conMidtab.find_all('table')
# 定义一个列表保存数据
lst = []
for table in tables:
# 获取所有的tr标签 注意要把前2个tr标签过滤掉
trs = table.find_all('tr')[2:]
for index, tr in enumerate(trs):
# 获取所有的td标签
# 是0的情况下所有的直辖市的数据都是正确的 省里面的除了第一个数据别的也是正确的
tds = tr.find_all('td')
city_td = tds[0]
# 判断什么情况下取第二个值 省会
if index == 0:
city_td = tds[1]
info = {}
city = list(city_td.stripped_strings)[0]
temp_td = tds[-2]
temp = list(temp_td.stripped_strings)[0]
info['city'] = city
info['temp'] = temp
lst.append(info)
print('city', city, 'temp', temp)
# break # 先打印北京
# print('-'*80)
return lst
# 写入数据
def writeData(lst):
with open('city_temp.csv', 'w', encoding='utf-8', newline='') as file_obj:
writer = csv.DictWriter(file_obj, titles)
writer.writeheader()
writer.writerows(lst)
def main():
lst = []
# 获取目标url
# url = 'http://www.weather.com.cn/textFC/hb.shtml' # 华北
# url = 'http://www.weather.com.cn/textFC/db.shtml' # 东北
# url = 'http://www.weather.com.cn/textFC/gat.shtml' # 港澳台 网页源码有问题
urls = ['http://www.weather.com.cn/textFC/hb.shtml', 'http://www.weather.com.cn/textFC/db.shtml',
'http://www.weather.com.cn/textFC/gat.shtml']
for url in urls:
lst += parse_page(url)
writeData(lst)
if __name__ == '__main__':
main()
爬虫和反爬虫的斗争
爬虫建议
- 尽量减少请求次数,保存获取到的HTML,供查错和重复使用
- 关注网站的所有类型的页面: H5页面, APP
- 多伪装:代理IP,随机请求头
- 利用多线程分布式,在不被发现的情况下我们尽可能的提高速度