Python—爬取豆瓣Top250(正则和Xpath比较)简单介绍Xpath
为了更加进一步理解和熟练使用python爬虫相关的第三方库和更多的去理解网页源码,相互比较第三方库的优劣的地方,对于豆瓣Top250的爬取我才用了纯正则表达式和纯Xpath去清晰网页源码,获得自己想要的数据。
Python标准库中提供了支持SAX和DOM的XML模块,但同时Python也提供了另外一个兼顾SAX和DOM优点的XML模块一ElementTree,ElementTree就像一个轻量级的DOM,可以读写XML文档,具有方便友好的API,且执行速度快,消耗内存少。目前ElementTree是解析和生成XML的最好选择,但还要结合Xpath匹配查找。
那么什么是XPath呢? XPath 是专门用来在XML文档中查找信息的语言。如果说XML是数据库,那么XPath就是SQL语言D。XPath将XML中的所有元素、属性和文本都看作节点(Node),根元素就是根节点,它没有父节点,属性称为属性节点,文本称为文本节点。除了根节点外,其他节点都有一个父节点,零或多个子节点和兄弟节点。
Xpath表达式:
表达式 | 说明 |
---|---|
nodename | 选择nodename子节点 |
. | 选择当前节点 |
/ | 路径指示符,指示当前目录分隔符 |
… | 选择父节点 |
// | 所有后代节点 |
[@attrib] | 选择指定属性的所有节点 |
[@attrib=“value”] | 选择指定属性等于value的所有节点 |
[position] | 指定位置 |
至于Xpath的具体使用方式,直接在代码中讲解。(其实也不用讲解一看就会)
首先观察豆瓣Top250网页的源码(直接使用谷歌浏览器进行访问,因为f12以后可以看到更加全面的信息)我的目标是250个电影的名字,观看的网页链接,电影关键字。
电影名字和对应的链接(分别在span标签和a标签中):
电影的关键字(在span标签中):
直接用xpath精准提取:
href = tree.xpath('//a[@class=""]/@href')
#print(href)
name = tree.xpath('//a[@class=""]/span[1]/text()')
#print(name)
keyword = tree.xpath('//p[@class="quote"]/span[@class="inq"]/text()')
和上面的Xpath表达式进行相比较的学习,是不是一看就明白呢。要是真的不会写Xpath表达式,更加简洁的方法是利用谷歌浏览器打开网页源码,选中指定元素,右键->Copy->Cipy Xpath,可以自己试一下这个效果,当然也可以在此Xpath表达式的基础上对其进行相应的修改。
对网页跳转链接进行分析:
'''
https://movie.douban.com/top250?start=0
https://movie.douban.com/top250?start=25
https://movie.douban.com/top250?start=50
'''
很容易发现参数规律增加而已,所有代码如下(在使用xpath之前一定先建立XML文档树):
import lxml
from lxml import etree
import requests
import time
header = {'Referer': 'https://movie.douban.com/top250',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
#获取网页的源码
def getHTMLText(url):
try:
r = requests.get(url,headers = header)
r.raise_for_status()
#r.encoding = r.apparent_encoding
return r.text
except:
return '获取网页源码错误'
'''
session = requests.Session()
session.get(url,headers = header,timeout = 3)
cookie = session.cookies
'''
if __name__ == '__main__':
'''
https://movie.douban.com/top250?start=0
https://movie.douban.com/top250?start=25
https://movie.douban.com/top250?start=50
'''
url_list = []
start_list = []
for number in range(10):
start_list.append(25*number)
for start in range(len(start_list)):
start = str(start_list[start])
url = 'https://movie.douban.com/top250?start=' + start
url_list.append(url)
#print(url_list)
#num = 0
for url in url_list:
time.sleep(2)
text = getHTMLText(url)
#用xpath对网页进行爬取
tree = etree.HTML(text) #在使用xpath之前一定先建立XML文档树
href = tree.xpath('//a[@class=""]/@href')
#print(href)
name = tree.xpath('//a[@class=""]/span[1]/text()')
#print(name)
keyword = tree.xpath('//p[@class="quote"]/span[@class="inq"]/text()')
for i in range(len(href)):
print("影片名称:{0}".format(name[i]))
print("影片关键字:{0}".format(keyword[i]))
print("影片链接:{0}".format(href[i]))
print("----------------------------------")
#num += 1
#print(num)
所执行的结果:
接下来我直接用纯正则表达式来进行数据定位爬取(上关键代码):
soup = BeautifulSoup(text,'html.parser')
for i in soup.find('ol',attrs = {'class':'grid_view'}).children:
#print(i)
re_href = r'<a href=".*?">'
href = re.findall(re_href,str(i))
#print(type(href))
href_list.append(href)
re_name = r'<span class="title">(\w+)</span>'
name = re.findall(re_name,str(i))
#print(name)
name_list.append(name)
re_keyword = r'<span class="inq">(.*?)</span>'
keyword = re.findall(re.compile(re_keyword),str(i))
#print(keyword)
keyword_list.append(keyword)
我采用了和BeautifulSoup库结合的方式,这样也可以准确的得到指定的数据信息,应该是自己的能力问题,所得到的结果不是尽如人意的好,看图片:
从图片中可以看出,因为是爬取多页,方便最后的输出,我将其保存在列表当中,但这就出现了一个问题,那就是正则表达式返回的结果接在列表当中,属于列表嵌套列表,而且不知为何返回了[ ]空列表的情况,应该是自己的正则表示的缘故吧,在此求大神指点,没办法,我又写了两个函数对此进行了处理:
def deal_with_href(list):
result = []
monment_list = dispose(list)
#print(monment_list)
for i in monment_list:
list = i.split('"')
#print(type(i))
result.append(list[1])
return result
#对列表进行处理
def dispose(list):
monment_list = []
for i in list[1::2]:
#print(i)
for j in i:
monment_list.append(j)
return monment_list
一个是解决[ ]空列表的问题,一个是对链接进行了提取,最后的结果:
其余部分代码:
url = 'https://movie.douban.com/top250'
header = {'Referer': 'https://movie.douban.com/top250',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
print("{:^10}\t{:^20}\t{:^110}".format('电影名称','电影关键字','电影链接'))
for i in range(len(name_list)):
print("{:^10}\t{:^20}\t{:^110}".format(name_list[i], keyword_list[i], href_list[i]))
在用二者进行爬取之后,我感觉首先应该看数据的返回格式,若是json格式,那么直接用其相应的方法进行处理,若想用网页源代直接进行数据的提取,那么我认为可以分情况和自己的喜好,Xpath的优点在于精准的定位,但其表达式自己写起来有点困难,BeautifulSoup库感觉和正则表达式结合起来使用很方便,前者缩小查找范围,后者直接进行提取。
以上是小白我的简介希望看到的小哥哥小姐姐们可以一起评论分想自己爬取心得,还有就是应该是自己的正则表示的缘故吧,在此求大神指点正则表达式
点赞更好哟!