一、数据解析
1.主题爬虫的技术构成
2.主题定义
一是,采用关键词集来描述一个主题。如果我们想抓取与 “大数据”有关的页面,最简单的方式就是用“大数据”这个词汇作为主题的定义,但是不含有大数据的页面也可能是与“大数据”相关的,例如一些讨论数据挖掘技术的页面。因此,采用关键词集合描述主题时,需要尽可能完整地考虑到所关注的主题可能涉及到关键词。
二是,对关键词集进行某种划分,通过对子主题的描述来实现对整个主题的定义。比如对于“大数据”这个主题,可以按照应用领域来划分大数据,也可以按照技术构成来划分,从而可以产生不同的子话题。
3.数据解析分类
(1)正则
(2)bs4
(3)xpath(重点,通用)
4.数据解析原理概述
解析的局部的文本内容都会在标签之间或者标签对应的属性中进行存储
(1)进行指定标签的定位
(2)标签或者标签对应的属性中存储的数据值进行提取(解析)
5.聚焦爬虫编码流程
爬取页面中指定的页面内容的编码流程:
指定url、发起请求、获取响应数据、数据解析、持久化存储
二、正则
1.样例解析
正则解析:
ex = ‘.?<img src=”(.?)” alt.*?‘
python xx=re.compile(r’abc’,string1)里面r的作用
r表示不进行转义
raw strings,不进行转义 r表示其后的字符串按原样表示,不使用转义字符
2.贪婪模式与非贪婪模式
参考文章链接:正则表达式之 贪婪与非贪婪模式详解(概述)
正则表达式中 . 与 .? 的区别
先看个例子
输入串A: 101000000000100
正则表达式一: 1.*1 匹配结果一:1010000000001 匹配方法: 先匹配至输入串A的最后, 然后向前匹配, 直到可以匹配到1, 称之为贪婪匹配。
正则表达式二: 1.*?1 匹配结果二:101 匹配方法: 匹配下一个1之前的所有字符, 称之为非贪婪匹配。
所有带有量词的都是非贪婪匹配: .*?, .+?, .{2,6}? 甚至 .??
仅从应用角度分析,可以这样认为,非贪婪模式,就是在整个表达式匹配成功的前提下,尽可能少的匹配,也就是所谓的“非贪婪”,通俗点讲,就是找到一个想要的捡起来就行了,至于还有没有没捡的就不管了。
3.豆瓣Top250例子的正则匹配
#对应的URL url = “https://movie.douban.com/top250“ # 网络链接的正则表达式
_findLink = re.compile(r’‘)
# 图片的正则表达式
findPic = re.compile(r’‘ ,re.S) #re.S:忽略换行符
# 影片片名的正则表达式
findTitle = re.compile(r’(.*)‘)
# 影片评分的正则表达式
findRating = re.compile(r’‘)
# 影片评价人数的正则表达式
findRatingPeople = re.compile(r’(\d*)人评价‘)
# 影片一句话评价的正则表达式
_findInq = re.compile(r’(.*)‘)
三、bs4进行数据解析
1.数据解析的原理:
- 标签定位
-
2.bs4数据解析的原理:
实例化一个BeautifulSoup对象, 并且将页面源码数据加载到该对象中
通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取
3.环境安装:
pip install bs4
-
4.如何实例化BeautifulSoup对象:
from bs4 import BeautifulSoup
对象的实例化:
1.将本地的html文档中的数据加载到该对象中
fp = open(‘ ./test.html’,’r’ , encoding=’utf-8’) soup = BeautifulSoup(fp, ‘lxml’ )
2.将互联网上获取的页面源码加载到该对象中
page text = response. text soup = BeatifulSoup(page text, ‘ lxml’ )
5.提供的用于数据解析的方法和属性:
- soup. tagName:返回的是文档中第一次出现的tagName对应的标签
- soup. find() :
find( ‘ tagName ‘ ) :等同于soup. div
属性定位:τ
soup. find( ‘div’ ,class_ /id/attr= ‘ song ‘)
soup. find_ all( ‘ tagName’ ) :返回符合要求的所有标签(列表)
6.select
select( ‘某种选择器(id, class, 标签…选择器) ‘) ,返回的是个列表。
- 层级选择器:
soup.select(‘.tang > ul > li > a’): >表示的是一个层级
soup.select(‘.tang > ul a’): 空格表示的多个层级
7.获取标签之间的文本数据
- soup. a. text/string/get_ text()
- text/get_ text() :可以获取某一个标签中所有的文本内容
- string:只可以获取该标签下面直系的文本内容
8.获取标签中属性值:
- soup.a[‘href’]
四、xpath
1.xpath解析原理
- 实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中.
- 调用etree对象中的XPath方法结合着XPath表达式实现标签的定位和内容的捕获。
2.环境的安装
pip install lxml
3.如何实例化一个etree对象
from lxml import etree
将本地的html文档中的源码数据加载到etree对象中:
tree = etree.parse(filePath)
可以将从互联网上获取的源码数据加载到该对象中
tree = etree.HTML( page_text)
-
4.xpath表达式
/:表示的是从网页的根节点开始定位。表示的是一个层级。
- ./:表示的是从当前级的节点开始定位。表示的是一个层级。
- //:表示的是多个层级。可以表示从任意位置开始定位。
- 属性定位://tag [@attrName=”attrValue”] 例如:div[@class=’song ‘]
- 索引定位://div[@class=”song”]/p[3] 索引是从1开始的。
- 取文本:
/text()获取的是标签中直系的文本内容
//text()标签中非直系的文本内容(所有的文本内容)
- 取属性:
/@attrName 例如:img/@src
5.xpath表达式的示范
网页内容:
获取“杜牧”文本: r = tree.xpath( ‘ //div[@class=”tang”]//li[5]/a/text() ‘ )[0]
获取“度蜜月”文本: r = tree. xpath( ‘//li[7]//text()’)
(得到的是一个列表) 获取所有文本: r = tree.xpath( ‘ //div[@class=”tang”]//text() ‘ )
网页图片内容和层级:
获取图片的网址: r = tree.xpath(‘//div[@class=”song]/img/@src’)
得到的列表,要取值的话就输入他的下标[1] 获取a标签下的网址: r = tree.xpath(‘//div[@class=”song]/a/@href’) 得到的列表,要取值的话就输入他的下标[1]
xpath函数的调用很灵活,注意看下面:
p=etree.HTML(html)
基准xpath表达式-30个房源节点对象列表
h_list=p.xpath(‘//ul[@class=”sellListContent”]/li[@class=”clear LOGVIEWDATA LOGCLICKDATA”]’)
所有列表节点对象
for h in h_list: item={}
名称
name_list=h.xpath(‘.//a[@data-el=”region”]/text()’)
判断列表是否为空
item['name']=name_list[0] **if** name_list **else** None
6.xpath的模糊匹配
参考链接:Xpath的模糊匹配用法 a. 用contains关键字,定位代码如下: driver.findElement(By.xpath(“//a[contains(@href, ‘logout’)]”)); 这句话的意思是寻找页面中href属性值包含有logout这个单词的所有a元素,由于这个退出按钮的href属性里肯定会包含logout,所以这种方式是可行的,也会经常用到。其中@后面可以跟该元素任意的属性名。 b. 用start-with,定位代码如下: driver.findElement(By.xpath(“//a[starts-with(@rel, ‘nofo’)])); 这种方式一般用于知道超链接上显示的部分或全部文本信息时,可以使用。 这句的意思是寻找rel属性以nofo开头的a元素。其中@后面的rel可以替换成元素的任意其他属性
五、遇到的问题
1.xpath获取的网页信息中含有‘\xa0’

解决办法:
网页爬虫中\xa0、\u3000等字符的解释及去除
name = [‘控方证人’, ‘\xa0/\xa0Witness for the Prosecution’, ‘\xa0/\xa0雄才伟略 / 情妇’,‘\xa0/\xa0控方证人’]
print(name)
# 方法1
_name1 = name[1]
name1.replace(u’\xa0’, u’ ‘)
print(name1)
# 方法2
name2 = name[2]
“” .join(name2.split())
print(name2)
# 方法3
_name3 = name[3]
unicodedata.normalize(‘NFKC’, name3)
print(name3)
2.使用自定义的类,出现“’module’ object is not callable”错误
参考文章:python中报TypeError: ‘module’ object is not callable 原因有哪些?
代码编写:
import movie …
movie是自定义的类
movietemp = movie(name,director,rating,ratingNum,comment,date,link,pic)
movieList.append(movietemp)
movietemp.detail()
错误提示:
解决办法:
将 import movie 改成 from movie import movie
3.正则匹配时,有个文本一直配不出内容
问题代码:
directorText = ‘\n 导演: 弗兰克·德拉邦特 Frank Darabont’
rr = re.compile(r’.导演: (.?)’,re.S)
director = rr.findall(directorText)
print(type(director),director)
问题展示:
问题解决:(未解决,只是用了个取巧的办法)
director = directorText.split(“导演: “)[1]
print(type(director),director)
还有个解决办法:
加上re.DOTALL
获取“杜牧”文本:
r = tree.xpath( ‘ //div[@class=”tang”]//li[5]/a/text() ‘ )[0]
获取“度蜜月”文本:
r = tree. xpath( ‘//li[7]//text()’)
(得到的是一个列表)
获取所有文本:
r = tree.xpath( ‘ //div[@class=”tang”]//text() ‘ )
网页图片内容和层级:
获取图片的网址:
r = tree.xpath(‘//div[@class=”song]/img/@src’)
得到的列表,要取值的话就输入他的下标[1]
获取a标签下的网址:
r = tree.xpath(‘//div[@class=”song]/a/@href’)
得到的列表,要取值的话就输入他的下标[1]

