网络爬虫是一种按照一定的规则自动地捕获万维网信息的程序或者脚本。爬虫程序通常从网站的某一个页面(通常是首页)开始,读取网页的内容,找到在网页中的其他链接地址,然后通过这些链接地址寻找下一个网页,然后一直循环下去,直到把这个网站所有的网页都捕获完为止。
网络爬虫一般分为两个步骤。
- 获取网页内容
- 多获取的网页内容进行分析处理。
1.获取网页内容——requests库
request的get()方法
url = "http://www.baidu.com"
response = requests.get(url)
从获取网页的角度上讲,requests的get()方法已经足以满足各种要求,get ()方法的返回值是一个Response对象,Response作为服务器对get()响应的结果,具有自己的属性和方法。
Response对象的主要属性如下:
属性 | 说明 |
---|---|
status_code | HTTP请求返回的状态码,200表示连接成功 |
text | HTTP响应内容的字符串形式,即:url对应的页面内容 |
encoding | HTTP响应的编码方式 |
content | HTTP响应内容的二进制形式 |
headers | 返回一个字典,内容是服务器的响应头 |
url | 返回请求的url |
apparent_encoding | 从内容中分析出的响应内容编码方式(备选编码方式) |
print(response.status_code) # 200
注意:
encoding和apparent_encoding的区别
encoding:如果header中不存在charset,则认为编码为ISO-8859-1
apparent_encoding:根据网页内容分析出的编码方式
综上所述,apparent_encoding比encoding更为准确
2.分析获取数据——beautifulsoup4库
使用requests库获取HTML网页内容后,需要解析HTML页面,这就需要用到能从HTML页面提取有用数据的函数库。beautifulsoup4库是一个非常优秀的Python扩展库,不仅可以解析HTML页面的内容,还可以读取XML文件内容。
BeautifulSoup将复杂的HTML文档转换成一个复杂的树形结构,每个节点都是Python对象。
解析以后全部html代码转变为4种类型:
基本对象类型
1、Tag——标签,最基本的信息组织单元,分别用<>和</>表明开头和结尾
1.1、标签Name属性——标签的名字,<p>…</p>的名字是’p’,格式:.name
1.2、标签Attributes属性——标签的属性,字典形式组织,格式:.attrs
2、NavigableString——标签内非属性字符串,<>…</>中的字符串,格式:.string
3、Comment——标签内字符串的注释部分,一种特殊的Comment类型(尖括号叹号表示注释开始:
)
4、BeautifulSoup对象(整个html对象soup)
**获取标签Tag: **
from bs4 import BeautifulSoup
import requests
def get_soup(url):
try:
r = requests.get(url, timeout=30)
# 如果状态不是200,引发HTTPError异常
r.raise_for_status()
r.encoding = r.apparent_encoding
soup = BeautifulSoup(r.text, "html.parser")
return soup
except requests.RequestException as e:
print(e)
return # 产生异常
url = "https://www.baidu.com"
soup = get_soup(url)
print(soup.a) #第一个a标签
print(soup.a.string) #第一个a标签的文本显示
print(type(soup.a.string)) #第一个a标签的对象类型,类型可以能是bs4.element.xxx
获取标签内容属性:
print(tag.name), # 标签的名称
print(tag.attrs), # 属性
print(tag.string) # 标签内的文本显示
print(tag.get_text()) # 获取标签内文本内容
搜索要用的到的两个函数:
find_all( name , attrs , recursive , text , **kwargs ) # 返回结果只包含一个元素的列表
find( name , attrs , recursive , text , **kwargs ) # 直接返回结果
搜索-按标签搜索
print(soup.find_all('a')[0]) #按字符串查询
print(soup.find_all(re.compile("^a"))[0]) #按正则表达式查询
print(soup.find_all(["a", "b"])[0]) #按列表查询
print(soup.find_all(True)[1]) #查询所有元素,第一个元素就是html元素,就是整个全文
搜索-按属性搜索
print(soup.find_all(id='headerImg')) #按属性值查询,data-*不能查询
print(soup.find_all(href=re.compile("#"))) #按属性值的正则表达式查询
print(soup.find_all(href=re.compile(".*index\.html"), target='_blank')) #按属性值列表查询
print(soup.find_all("a", class_="current")) #标签属性联合搜索,class 是 python 的关键词,所以加了_
# 也可以这样写:print(soup.find_all("a", {'class':"current"}))
print(soup.find_all(attrs={"class": "current"})) #搜索包含指定属性值的元素,返回列表
搜索-按文本搜索
print(soup.find_all(text="首页")) #按文本搜素,接受的参数与按标签搜索一样
print(soup.find_all("a", limit=2,recursive=False)) #以上所有搜索都可以用limit限定最大搜索到的数目,用recursive限定只搜索直接子节点
搜索-按css选择器名称搜索
注意:以下返回的都是列表
print(soup.select('title')) # 按名称
print(soup.select('.current')) # 按类名
print(soup.select('#headerImg')) # 按id
print(soup.select('li .current')) # 后代查询
print(soup.select("head > title")) # 子标签查询
print(soup.select('a[class="current"]')) # 属性查询
节点遍历-向下遍历
for child in soup.body.children: # 直接子节点列表,迭代类型,需要用循环方式,空格、换行也是子节点
print("body's child:"+str(child.name))
节点遍历-同胞遍历
firstli=soup('li')[0] # 等价于soup.li
print(firstli.next_sibling) # 注意空格换行也是节点
print(firstli.previous_sibling) # 注意空格换行也是节点
for sibling in firstli.next_siblings: #注意空格换行也是节点
print('next_siblings:',sibling)
for sibling in firstli.previous_siblings: # 注意空格换行也是节点
print('previous_siblings:'+str(sibling))