python list find_一篇文章带你了解Python爬虫常用选择器

97b84ec2574643d0f75f0489ca17349b.png

原创 麦自香 Python爬虫案例

当我们初学爬虫的时候,我们都会选择一些最基本的网站,往往不带任何反爬措施。比如某个博客站点,我们要爬全站的话,就顺着列表页爬到文章页,再把文章的时间、作者、正文等信息爬下来就可以了。那代码怎么写呢?

一般的情况我们都是使用 Python 的 requests 等库就够了,写一个基本的逻辑,顺着把一篇篇文章的源码获取下来,解析的话会用到 XPath、BeautifulSoup、或者正则表达式,再把文本写入存下来就完事了。代码很简单,就几个方法调用。逻辑很简单,几个循环加存储。

之所以这么说,是因为接下来我们想要对古诗文网站来进行爬取,分别用正则表达式、BeautifulSoup、Xpath、通过这些代码来给大家介绍下Python常用的选择器,以及他们之间的区别,让我们对Python的选择器有一个更深的认识。

一、正则表达式

正则表达式为我们提供了抓取数据的快捷方式。虽然该正则表达式更容易适应未来变化,但又存在难以构造、可读性差的问题。接下来我们使用正则表达式爬取古诗文网站,代码如下:

# 使用正则表达式解析网页元素

# 关键点:直接找每个个体里面相同位置的元素,用findall一次提取出来到列表中

import requests

import re

DATA = []

def getHTMLtext(url, headers, timeout=10):

try:

resp = requests.get(url, headers=headers, timeout=timeout)

resp.raise_for_status

resp.encoding = 'utf-8'

return resp.text

except:

return ''

def reParser(text):

name_list = re.findall(r'<div class="yizhu".*?<b>(.*?)</b>', text, re.S) # re.DOTALL

dynasty_list = re.findall(r'<p class="source">.*?target="_blank">(.*?)</a>', text, re.S)

author_list = re.findall(r'<p class="source">.*?target="_blank">.*?</a>.*?target="_blank">(.*?)</a>', text, re.S)

row_content_list = re.findall(r'<div class="contson".*?>(.*?)</div>', text, re.S)

content_list = []

for content in row_content_list:

temp = re.sub(r'<.*?>', '', content) # 这里一定要记得不要写成了贪婪匹配哦

content_list.append(temp.strip()) # 去除空格

for value in zip(name_list, dynasty_list, author_list, content_list):

name, dynasty, author, content = value

poetry_dict = {

'诗词名': name,

'朝代': dynasty,

'作者': author,

'内容': content,

}

DATA.append(poetry_dict)

def print_poetry(data):

for every_poetry in data:

print(every_poetry['诗词名'])

print(every_poetry['朝代'] + ':' + every_poetry['作者'])

print(every_poetry['内容'])

print("n" + '*' * 50 + "n")

if __name__ == '__main__':

row_url = '网页发生错误'

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}

num = input('请输入要爬取的页数(1-100):')

for i in range(eval(num)):

url = row_url.format(i + 1)

# print(url)

text = getHTMLtext(url, headers)

if text == '':

print('url: {} 访问失败'.format(url))

else:

reParser(text)

TOP10 = DATA[:10]

# print(TOP10)

print_poetry(TOP10)

利用正则表达式实现对目标信息的精准采集,此外 ,我们都知道,网页时常会产生变更,导致网页中会发生一些微小的布局变化时,此时也会使得之前写好的正则表达式无法满足需求,而且还不太好调试。当需要匹配的内容有很多的时候,使用正则表达式提取目标信息会导致程序运行的速度减慢,需要消耗更多内存。

二、BeautifulSoup

BeautifulSoup是一个非常流行的 Pyhon 模块,简称Bs4。该模块可以解析网页,并提供定位内容的便捷接口。通过

pip install beautifulsoup4

就可以实现该模块的安装了。演示代码如下:

# 使用bs4提取网页,先利用find_all解析

import requests

from bs4 import BeautifulSoup

DATA = []

def getHTMLtext(url, headers, timeout=10):

try:

resp = requests.get(url, headers=headers, timeout=timeout)

resp.raise_for_status

resp.encoding = 'utf-8'

return resp.text

except:

return ''

def bs4_find_all_Parser(text):

soup = BeautifulSoup(text, 'lxml')

sons = soup.find_all('div', class_="sons")[:10] # 返回一个<class 'bs4.element.ResultSet'>,每一个元素都是Tag类型

# 注意:上一步里面返回了一些其他的元素,我们可以提取出前面的10项,那是我们需要用到的

# print(sons)

for son in sons:

name = son.find('b').get_text()

print(name)

dynasty_author = son.find('p', class_="source").get_text()

print(dynasty_author)

content = son.find('div', class_="contson").get_text()

print(content)

if __name__ == '__main__':

url = '古诗文网-古诗文经典传承'

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}

text = getHTMLtext(url, headers)

if text == '':

print('url: {} 访问失败'.format(url))

else:

bs4_find_all_Parser(text)

使用 Bs4的第一步是将己下载的 HTML 内容解析为 soup文档。由于大多数网 页都不具备良好的HTML 格式,此Bs4需要对实际格式进行确定。Bs4能够正确解析缺失的引号并闭合标签,此外还会添加<html >和<body>标签使其成为完整的HTML文档。通常使用find() 和find_all()方法来定位我们需要的元素。

如果你想了解BeautifulSoup全部方法和参数,可以查阅BeautifulSoup的官方文档。虽然BeautifulSoup在代码的理解上比正则表达式要复杂一些,但是其更加容易构造和理解。

三、lxml

Xpath,使lxml 模块的第一步和BeautifulSoup一样,也是将有可能不合法的HTML 解析为统一格式。虽然lxml可以正确解析属性两侧缺失的引号,并闭合标签,不过该模块没有额外添加<html >和<body>标签 。

lxml也是需要提前安装的,通过:

pip install lxml

演示代码如下:

# xpath代码展示

import requests

from lxml import etree

DATA = []

def getHTMLtext(url, headers, timeout=10):

try:

resp = requests.get(url, headers=headers, timeout=timeout)

resp.raise_for_status

resp.encoding = 'utf-8'

return resp.text

except:

return ''

def xpathParser(text):

htmlElement = etree.HTML(text) # <class 'lxml.etree._Element'>

name_list = htmlElement.xpath('/html/body/div[2]/div[1]/div/div[1]/p[1]/a/b/text()')

dynasty_list = htmlElement.xpath('/html/body/div[2]/div[1]/div/div[1]/p[2]/a[1]/text()')

author_list = htmlElement.xpath('/html/body/div[2]/div[1]/div/div[1]/p[2]/a[2]/text()')

content_list = []

poetries = htmlElement.xpath(

'//div[@class="contson" and contains(@id,"contson")]') # 返回一个列表,里面每一个都是'lxml.etree._Element'

# print(etree.tostring(poetries[0],encoding = 'utf-8').decode('utf-8'))

for poetry in poetries:

row_content = ''.join(poetry.xpath('.//text()')) # 这里的.可千万不能掉,否则会忽略掉poetry哦

content_list.append(row_content.replace('n', ''))

for value in zip(name_list, dynasty_list, author_list, content_list):

name, dynasty, author, content = value

poetry_dict = {

'诗词名': name,

'朝代': dynasty,

'作者': author,

'内容': content,

}

DATA.append(poetry_dict)

def print_poetry(data):

for every_poetry in data:

print(every_poetry['诗词名'])

print(every_poetry['朝代'] + ':' + every_poetry['作者'])

print(every_poetry['内容'])

print("n" + '*' * 50 + "n")

if __name__ == '__main__':

row_url = '网页发生错误'

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}

num = input('请输入要爬取的页数(1-100):')

for i in range(eval(num)):

url = row_url.format(i + 1)

text = getHTMLtext(url, headers)

if text == '':

print('url: {} 访问失败'.format(url))

else:

xpathParser(text)

TOP10 = DATA[:10]

print_poetry(TOP10)

在线复制Xpath表达式可以很方便的复制Xpath表达式。但是通过该方法得到的Xpath表达式放在程序中一般不能用,而且长的没法看。所以Xpath表达式一般还是要自己亲自上手。

如果你的爬虫瓶颈是下载网页,也不是抽取数据的话,那么使用较慢的方法(如BeautifulSoup) 也不成问题。如果只需抓取少量数据,并且想要避免额外依赖的话,那么正则表达式可能更加适合。不过,通常情况下,lxml是抓取数据的最好选择,这是因为该方法既快速又健壮,而正则表达式和BeautifulSoup只在某些特定场景下有用。

Lxml模块使用 C语言编写,其解析速度比 BeautiflSoup更快,而且其安装过程也更为复杂,在此小编就不赘述啦。XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值