本周开始学习爬虫,主要是学习了HTML的一些语法以及python的beautifulsoup软件包来对HTML解析。
爬虫
定义:自动批量下载网络资源
抓取目标分类
基于目标网页特征 | 基于目标网页特征的爬虫所抓取、存储并索引的对象一般为网站或网页。 根据种子样本获取方式可分为: (1)预先给定的初始抓取种子样本; (2)预先给定的网页分类目录和与分类目录对应的种子样本,如Yahoo!分类结构等; (3)通过用户行为确定的抓取目标样例,分为: (a)用户浏览过程中显示标注的抓取样本; (b)通过用户日志挖掘得到访问模式及相关样本。 |
基于目标数据模式 | 基于目标数据模式的爬虫针对的是网页上的数据,所抓取的数据一般要符合一定的模式,或者可以转化或映射为目标数据模式。 |
基于领域概念 | 建立目标领域的本体或词典,用于从语义角度分析不同特征在某一主题中的重要程度。 |
网页搜索策略
广度优先搜索 | 在抓取过程中,在完成当前层次的搜索后,才进行下一层次的搜索。 |
最佳优先搜索 | 按照一定的网页分析算法,预测候选URL与目标网页的相似度,或与主题的相关性,并选取评价最好的一个或几个URL进行抓取。 |
深度优先搜索 | 从起始网页开始,选择一个URL进入,分析这个网页中的URL,选择一个再进入。 |
HTML语法
这里写一下遇到的
<dt>
标签定义一个描述列表的项目 / 名字。
<dt>
标签与 <dl>
(定义一个描述列表)和 <dd>
(描述每一个项目 / 名字)一起使用
<a> 标签定义超链接,用于从一个页面链接到另一个页面。
<b> 标签规定粗体文本。
还有一些太多了,偷一下别人写的:
格式标签:
文本标签:
beautifulsoup
BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.
主要的使用方式为
from bs4 import BeautifulSoup
html ='''
<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, "html.parser")
"html.parser"分析出HTML里面的标签、数据等等,是一种处理HTML的简便途径
beautifulsoup当中有四种对象
- Tag
- NavigableString
- BeautifulSoup
- Comment
Tag就是 HTML 中的一个个标签,如<title></title>可以如下方式获取
# 获取html代码中的titile标签
print(soup.title)
对于 Tag,它有name 和 attrs两个重要的属性 :
#获取name
print(soup.title.name)
print(soup.a.name)
print(soup.p.name)
#单独获取某个属性
print(soup.p['class'])
#['title']
print(soup.p.get('class'))
#['title']
print(soup.a.attras)
#{'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'}
#删除属性
del soup.p['class']
获取父、子节点
通过tag的 .contents 属性可以将tag的子节点以列表的方式输出
通过tag的 .children 生成器,可以对tag的子节点进行循环
for i in soup.p.children:
print(i)
#
标准选择器find_all()
可以自定义attras来查找:
print(soup.find_all(attrs={"id":"link1"}))
#[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
print(soup.find_all(attrs={"id":"link1"})[0].get_text())
#Elsie
汽车之家爬取
本周主要学习了beautiful soup后,就选择了汽车之家进行了爬取练习了一下。
首先是自定义了一个headers,对汽车之家"https://www.autohome.com.cn/grade/carhtml/B.html"这个url进行request,得到html。
它大概是长这个样子的:
def get_page(Url):
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"
}
response = requests.get(url=Url,headers=headers)
soup = BeautifulSoup(response.text,"html.parser")
return soup
然后列了一个字典,存储要爬取的信息。
info = {'brand': '', 'producer': '','car_series': '', 'car_series_id': '', 'car_price': ''}
对html分析一下:
<dl>标签用于包含所有汽车品牌的列表。
可以看出还是比较清楚的,<dl>-><dt>-><div>-><a>就可以找到相应的汽车品牌。
<dl>-><dd>-><div>-><a>就可以找到相应的汽车生产商。
<dl>-><dd>-><ul>-><li>-><h4>-><a>就可以找到相应的汽车类型。
<dl>-><dd>-><ul>-><li>下面有两个div标签
<dl>-><dd>-><ul>-><li>-><div>-><a>就可以找到相应的汽车指导价。
实际代码当中利用find_all('a', attrs={'class': 'red'})就可以了。
另一个<div>标签存的都是一些超链接,可以通过request访问,跳转再次爬取这些页面的数据。
具体的代码如下:
for brand in all_cars:
print(brand['id'])
car_types = brand.find_all('dd')
info['brand'] = brand.dt.div.a.string.strip()
for car_type in car_types:
producers = soup.find_all('div', attrs={'class': 'h3-tit'})
for producer in producers:
info['producer']=producer.a.string.strip()
cars = producer.find_next('ul')
for car in cars.find_all('li', attrs={'id': True}):
info['car_series_id'] = car['id']
car_conf_sub=ar_conf.find_all('div', attrs={'class': 'pzbox'})
car_conf_details=car_conf_sub.find_all('div', attrs={'id': 'config_data'})
car_conf_detail =car_conf_details.find_all('table', attrs={'id': 'tab_0'})
car_conf_detail =car_conf_details.find_all('tr', attrs={'id': 'tr1'})
for car_conf_detail = in
info['car_series'] = car.h4.a.string.strip()
#因为可能为空值,所以先判断,若非空就取列表内元素的string赋值给价格,若为空则自行设置为空
if car.find_all('a', attrs={'class': 'red'}):
info['car_price']=car.find_all('a', attrs={'class': 'red'})[0].string.strip()
else:
info['car_price']='无价格'
print(info.items())
通过字典形式输出大概就是这个样子:
dict_items([('brand', '奔驰'), ('producer', '北京奔驰'), ('car_series', '奔驰EQE SUV'), ('car_series_id', 's6975'), ('car_price', '无价格')])
dict_items([('brand', '奔驰'), ('producer', '北京奔驰'), ('car_series', '奔驰A级'), ('car_series_id', 's4764'), ('car_price', '21.48-26.48万')])
dict_items([('brand', '奔驰'), ('producer', '北京奔驰'), ('car_series', '奔驰A级AMG'), ('car_series_id', 's5217'), ('car_price', '39.51-39.98万')])
做完这些之后,想通过超链接跳转到配置页面,顺便把车型的配置爬一下,但是遇到了一个问题:
像这样的参数,在html当中是下图这样存储的:
爬配置的方法,目前就是通过前面那个html能从有的标签attras里面获得相对应的车型编号,然后对照一下配置页面的url,其实可以转过去,具体就先做了这一个方法,可能有点蠢,因为跑起来加了这些输出明显的慢了好多。
list_str = list(car['id'])
list_str.pop(0)
config= ''.join(list_str)
u = 'https://car.autohome.com.cn/config/series/'+config+'.html#pvareaid=3454437'
car_conf=get_page(u)
而且它的很多配置都是以类来表示的,所以爬下来我也不知道这个是什么东西,暂时就是这些问题,然后本周就做了这么多工作。