- 正则
- xpath
- bs4
soup.a.attrs 返回一字典,里面是所有属性和值
soup.a['href'] 获取href属性
soup.a.string
soup.a.text
soup.a.get_text()
- 解析效率比较高
- 通用性最强的
- 环境安装:pip install lxml
- 解析原理:
- 实例化一个etree对象且将即将被解析的页面源码数据加载到该对象中
- 使用etree对象中的xpath方法结合着xpath表达式进行标签定位和数据提取
- 实例化etree对象
- etree.parse('本地文件路径')
- etree.HTML(page_text)
在网页数据解析当中,re正则解析是比较费劲的,而且非常容易出错,网页数据结构一旦出错,则容易报出异常,而且想要匹配好正则,你的正则表达式需要熟练,不然你得一步步去尝试了,某些网页数据解析还真的只能用正则表达式去匹配。
如果你有接触过火车头采集器,那么对于正则,应该不会陌生!
实例的方式为大家展示Python爬虫三种解析方式
Pyhton360搜索排名查询
关于搜索排名的结果查询,前面有分享过Python百度的搜索排名查询
360搜索排名查询,大同小异,比较烦人的就是协议头的处理
#构建协议头
def ua():
ua=UserAgent()
headers={
'Cookie': 'QiHooGUID=622250714BFE7FEEBC7BE97B1768B7F1.1578470720454; _S=ilmjtet5usmi3a5005tq7of442; opqopq=d8a79fec6212514efe440041e132813c.1578470720',
'Referer': 'https://www.so.com/haosou.html',
"User-Agent":ua.random,
}
return headers
第一个就是ua,还有就是cookies,最后一个就是Referer的添加,这个在图片的反爬中比较常见!
协议头不对的反馈,相信你也会碰到!
三种解析方式的处理,那就在细节上有小差异,同时还有部分数据的处理!
数据处理的关键点:
1.eval()函数
将str转为字典,提取排名
2.排名为空的情况
这里我用异常处理了
re正则的话写了 if else判断处理
3.xpath多个数据获取后的处理
title=''.join(li.xpath('.//a[1]//text()')[:-1]) #标题字符串处理
join函数以及切片的处理
bs4解析
#bs4获取数据
def get_bs4search(keyword,num,cxurl):
jg = []
for i in range(1,int(num)+1):
print(f'正在查询{i}页排名...')
url="https://www.so.com/s?q=%s&pn=%d" % (keyword,i)
req=get_html(url)
soup=BeautifulSoup(req,"html.parser")
lis=soup.find("ul",class_="result").find_all("li",class_="res-list")
print(len(lis))
for li in lis:
title=li.find("a").get_text()
site_url=li.find("a")['href']
try:
pos=eval(li.find("a")['data-res'])['pos'] #eval()函数,将str转为字典,提取排名
pm=(i-1)*10+pos
except:
pm="空"
print(pm,title,site_url)
cxjg=cxwz(keyword, i, pm, title, site_url, cxurl)
if cxjg !=[]:
jg.append(cxjg)
time.sleep(5)
print("排名查询结果:")
print("-----------------------------------------")
if jg == []:
print("该关键词无排名!")
else:
print('\n'.join(jg))
print("-----------------------------------------")
print("查询排名结束")
find以及find_all方法
#find方法
#find只能找到符合要求的第一个标签,他返回的是一个对象
soup.find('a')
soup.find('a', class_='xxx')
soup.find('a', title='xxx')
soup.find('a', id='xxx')
soup.find('a', id=re.compile(r'xxx'))
#find_all
#返回一个列表,列表里面是所有的符合要求的对象
soup.find_all('a')
soup.find_all('a', class_='wang')
soup.find_all('a', id=re.compile(r'xxx'))
soup.find_all('a', limit=2) #提取出前两个符合要求的a
当然还有个select方法,这里我没有用,可自行采用了解!
#选择,选择器 css中
常用的选择器
标签选择器、id选择器、类选择器 层级选择器**
div h1 a 后面的是前面的子节点即可
div > h1 > a 后面的必须是前面的直接子节点
属性选择器 input[name='hehe'] select('选择器的') 返回的是一个列表,
列表里面都是对象 find find_all select不仅适用于soup对象,
还适用于其他的子对象,
如果调用子对象的select方法,
那么就是从这个子对象里面去找符合这个选择器的标签。
xpath解析
#xpath获取数据
def get_xmlsearch(keyword,num,cxurl):
jg = []
for i in range(1,int(num)+1):
print(f'正在查询{i}页排名...')
url="https://www.so.com/s?q=%s&pn=%d" % (keyword,i)
req=get_html(url)
html=etree.HTML(req)
lis=html.xpath('//ul[@class="result"]/li[@class="res-list"]')
for li in lis:
title=''.join(li.xpath('.//a[1]//text()')[:-1]) #标题字符串处理
site_url=li.xpath('.//a[1]/@href')[0]
try:
pos=eval(li.xpath('.//a[1]/@data-res')[0])['pos'] #eval()函数,将str转为字典,提取排名
pm=(i-1)*10+pos
except:
pm="空"
print(pm,title,site_url)
cxjg = cxwz(keyword, i, pm, title, site_url, cxurl)
if cxjg != []:
jg.append(cxjg)
time.sleep(5)
print("排名查询结果:")
print("-----------------------------------------")
if jg == []:
print("该关键词无排名!")
else:
print('\n'.join(jg))
print("-----------------------------------------")
print("查询排名结束")
re正则解析
#re正则获取数据
def get_research(keyword,num,cxurl):
jg = []
for i in range(1,int(num)+1):
print(f'正在查询{i}页排名...')
url="https://www.so.com/s?q=%s&pn=%d" % (keyword,i)
req=get_html(url)
ul=re.findall(r'<ul class="result">(.+?)<div id="side">',req,re.S)[0]
lis=re.findall(r'<li class="res-list"(.+?)</li>',ul,re.S)
for li in lis:
title=re.findall(r'<a href=".+?>(.+?)</a>',li,re.S)[0]
title=title.replace('<em>','').replace('</em>','') #标题字符串处理
site_url=re.findall(r'<a href="(.+?)".+?>.+?</a>',li,re.S)[0]
if "data-res" in li:
pos=re.findall(r',"pos":(.+?),"m":',li,re.S)[0]
pm = (i - 1) * 10 + int(pos)
else:
pm="空"
print(pm,title,site_url)
cxjg = cxwz(keyword, i, pm, title, site_url, cxurl)
if cxjg != []:
jg.append(cxjg)
time.sleep(5)
print("排名查询结果:")
print("-----------------------------------------")
if jg == []:
print("该关键词无排名!")
else:
print('\n'.join(jg))
print("-----------------------------------------")
print("查询排名结束")
运行效果:
测试就找到一个作弊站。。
附完整源码:
#360搜索排名查询
#20200108 by 微信:huguo00289
# -*- coding: utf-8 -*-
import requests,re,time
from fake_useragent import UserAgent
from bs4 import BeautifulSoup
from lxml import etree
#构建协议头
def ua():
ua=UserAgent()
headers={
'Cookie': 'QiHooGUID=622250714BFE7FEEBC7BE97B1768B7F1.1578470720454; _S=ilmjtet5usmi3a5005tq7of442; opqopq=d8a79fec6212514efe440041e132813c.1578470720',
'Referer': 'https://www.so.com/haosou.html',
"User-Agent":ua.random,
}
return headers
#获取访问数据
def get_html(url):
response=requests.get(url,headers=ua(),timeout=10)
print(response.status_code)
req=response.content.decode('utf-8')
return req
#获取搜索结果
#bs4获取数据
def get_bs4search(keyword,num,cxurl):
jg = []
for i in range(1,int(num)+1):
print(f'正在查询{i}页排名...')
url="https://www.so.com/s?q=%s&pn=%d" % (keyword,i)
req=get_html(url)
soup=BeautifulSoup(req,"html.parser")
lis=soup.find("ul",class_="result").find_all("li",class_="res-list")
print(len(lis))
for li in lis:
title=li.find("a").get_text()
site_url=li.find("a")['href']
try:
pos=eval(li.find("a")['data-res'])['pos'] #eval()函数,将str转为字典,提取排名
pm=(i-1)*10+pos
except:
pm="空"
print(pm,title,site_url)
cxjg=cxwz(keyword, i, pm, title, site_url, cxurl)
if cxjg !=[]:
jg.append(cxjg)
time.sleep(5)
print("排名查询结果:")
print("-----------------------------------------")
if jg == []:
print("该关键词无排名!")
else:
print('\n'.join(jg))
print("-----------------------------------------")
print("查询排名结束")
#xpath获取数据
def get_xmlsearch(keyword,num,cxurl):
jg = []
for i in range(1,int(num)+1):
print(f'正在查询{i}页排名...')
url="https://www.so.com/s?q=%s&pn=%d" % (keyword,i)
req=get_html(url)
html=etree.HTML(req)
lis=html.xpath('//ul[@class="result"]/li[@class="res-list"]')
for li in lis:
title=''.join(li.xpath('.//a[1]//text()')[:-1]) #标题字符串处理
site_url=li.xpath('.//a[1]/@href')[0]
try:
pos=eval(li.xpath('.//a[1]/@data-res')[0])['pos'] #eval()函数,将str转为字典,提取排名
pm=(i-1)*10+pos
except:
pm="空"
print(pm,title,site_url)
cxjg = cxwz(keyword, i, pm, title, site_url, cxurl)
if cxjg != []:
jg.append(cxjg)
time.sleep(5)
print("排名查询结果:")
print("-----------------------------------------")
if jg == []:
print("该关键词无排名!")
else:
print('\n'.join(jg))
print("-----------------------------------------")
print("查询排名结束")
#re正则获取数据
def get_research(keyword,num,cxurl):
jg = []
for i in range(1,int(num)+1):
print(f'正在查询{i}页排名...')
url="https://www.so.com/s?q=%s&pn=%d" % (keyword,i)
req=get_html(url)
ul=re.findall(r'<ul class="result">(.+?)<div id="side">',req,re.S)[0]
lis=re.findall(r'<li class="res-list"(.+?)</li>',ul,re.S)
for li in lis:
title=re.findall(r'<a href=".+?>(.+?)</a>',li,re.S)[0]
title=title.replace('<em>','').replace('</em>','') #标题字符串处理
site_url=re.findall(r'<a href="(.+?)".+?>.+?</a>',li,re.S)[0]
if "data-res" in li:
pos=re.findall(r',"pos":(.+?),"m":',li,re.S)[0]
pm = (i - 1) * 10 + int(pos)
else:
pm="空"
print(pm,title,site_url)
cxjg = cxwz(keyword, i, pm, title, site_url, cxurl)
if cxjg != []:
jg.append(cxjg)
time.sleep(5)
print("排名查询结果:")
print("-----------------------------------------")
if jg == []:
print("该关键词无排名!")
else:
print('\n'.join(jg))
print("-----------------------------------------")
print("查询排名结束")
#查询网址是否存在排名
def cxwz(keyword,i,pm,title,site_url,cxurl):
if cxurl in site_url:
cxjg = f'关键词:{keyword},页码:第{i}页,排名:{pm},标题:{title},网址:{site_url}'
print(f'关键词:{keyword},页码:第{i}页,排名:{pm},标题:{title},网址:{site_url}')
else:
cxjg=[]
return cxjg
if __name__=="__main__":
while True:
keyword = input('请输入要查询的关键词:')
num = input('请输入要查询的页码数:')
url = input('请输入要查询的主域名:')
try:
get_bs4search(keyword,num,url)
except IndexError as e:
print(e)
print("查询排名失败!")
本文分享自 Python与SEO学习 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!