我正在使用BeautifulSoup开发python网络抓取工具,该抓取工具解析this网站上的“产品列表”,并为每个产品列表提取一些信息(例如价格,供应商等)。 我能够提取许多此类信息,但是其中一个(即产品数量)似乎是从 raw html中 hidden 隐藏的。通过浏览器查看网页,我看到的是(单位=单位):
product_name 1 unid $10.00
但该html不会显示我可以提取的任何整数值。它显示以下html文本:
<div class="e-col5 e-col5-offmktplace ">
<div class="kWlJn zYaQqZ gQvJw"> </div>
<div class="imgnum-unid"> unid</div>
</div>
我的问题是,我如何获取存储产品数量的e-col5
的隐藏内容?
import re
import requests
from bs4 import BeautifulSoup
page = requests.get("https://ligamagic.com.br/?view=cards%2Fsearch&card=Hapatra%2C+Vizier+of+Poisons")
soup = BeautifulSoup(page.content, 'html.parser')
vendor = soup.find_all('div', class_="estoque-linha", mp="2")
print(vendor[1].find(class_='e-col1').find('img')['title'])
print(vendor[1].find(class_='e-col2').find_all(class_='ed-simb')[1].string)
print(vendor[1].find(class_='e-col5'))
答案 0 :(得分:2)
unid
保存在JS数组中
vetFiltro[0]=["e3724364",0,1,....];
1
是unid,您可以使用正则表达式获取它
# e-col5
unitID = vendor[1].get('id').replace('line_', '') # line_e3724364 => e3724364
regEx = r'"%s",\d,(\d+)' % unitID
unit = re.search(regEx, page.text).group(1)
print(unit + ' unids')
答案 1 :(得分:1)
如果仔细观察,unid
只是div中由class
移动到正确数字的图像。
例如unid
1:
.jLsXy {
background-image: url(arquivos/up/comp/imgunid/files/img/181224lSfWip8i1lmcj2a520836c8932ewcn.jpg);
}
是包含数字的图像。
.gBpKxZ {
background-position: -424px -23px;
}
是数字1的类
因此找到与数字匹配的CSS并创建表格(简便方法),但不是最佳方法。
编辑: 似乎每次重新加载时都会更改position(class),因此将数字与图像进行匹配变得更加困难:(因此,数字1可以从很多地方获取。
Edit2
我正在使用chrome devtools。
如果您检查unid
,也会发现每个类别的css
。
因此,在检查了网址之后就很清楚了。
答案 2 :(得分:1)
@ewwink找到了掏出unid
的方法,但无法掏出价格。我试图在这个答案中拉出价格。
目标div代码段:
<div mp="2" id="line_e3724364" class="estoque-linha primeiro"><div class="e-col1"><a href="b/?p=e3724364" target="_blank"><img title="Rayearth Games" src="//www.lmcorp.com.br/arquivos/up/ecom/comparador/155937.jpg"></a></div><div class="e-col9-mobile"><div class="e-mob-edicao"><img src="//www.lmcorp.com.br/arquivos/up/ed_mtg/AKH_R.gif" height="19"></div><div class="e-mob-edicao-lbl"><p>Amonkhet</p></div><div class="e-mob-preco e-mob-preco-desconto"><font color="gray" class="mob-preco-desconto"><s>R$ 1,00</s></font><br>R$ 0,85</div></div><div class="e-col2"><a href="./?view=cards/search&card=ed=akh" class="ed-simb"><img src="//www.lmcorp.com.br/arquivos/up/ed_mtg/AKH_R.gif" height="21"></a><font class="nomeedicao"><a href="./?view=cards/search&card=ed=akh" class="ed-simb">Amonkhet</a></font></div><div class="e-col3"><font color="gray" class="mob-preco-desconto"><s>R$ 1,00</s></font><br>R$ 0,85</div>
<div class="e-col4 e-col4-offmktplace">
<img src="https://www.lmcorp.com.br/arquivos/img/bandeiras/pten.gif" title="Português/Inglês"> <font class="azul" onclick="cardQualidade(3);">SP</font>
</div>
<div class="e-col5 e-col5-offmktplace "><div class="cIiVr lHfXpZ mZkHz"> </div> <div class="imgnum-unid"> unid</div></div><div class="e-col8 e-col8-offmktplace "><div><a target="_blank" href="b/?p=e3724364" class="goto" title="Visitar Loja">Ir à loja</a></div></div></div>
如果我们仔细观察,我们可以
for item in soup.findAll('div', {"id": re.compile('^line')}):
print(re.findall("R\$ (.*?)</div>", str(item), re.DOTALL))
输出[截断]:
['10,00</s></font><br/>R$ 8,00', '10,00</s></font><br/>R$ 8,00']
['9,50</s></font><br/>R$ 8,55', '9,50</s></font><br/>R$ 8,55']
['9,50</s></font><br/>R$ 8,55', '9,50</s></font><br/>R$ 8,55']
['9,75</s></font><br/>R$ 8,78', '9,75</s></font><br/>R$ 8,78']
[]
[]
它提取出大块,我们将获得价格。 但这还会跳过多个项目。
要获取所有数据,我们可以使用OCR API和Selenium来完成此操作。我们可以使用以下代码段捕获感兴趣的元素:
from selenium import webdriver
from PIL import Image
from io import BytesIO
fox = webdriver.Firefox()
fox.get('https://ligamagic.com.br/?view=cards%2Fsearch&card=Hapatra%2C+Vizier+of+Poisons')
#element = fox.find_element_by_id('line_e3724364')
element = fox.find_elements_by_tag_name('s')
location = element.location
size = element.size
png = fox.get_screenshot_as_png() # saves screenshot of entire page
fox.quit()
im = Image.open(BytesIO(png)) # uses PIL library to open image in memory
left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']
im = im.crop((left, top, right, bottom)) # defines crop points
im.save('screenshot.png') # saves new cropped image
从https://stackoverflow.com/a/15870708寻求帮助。
我们可以像上面一样使用re.findall()
进行迭代,以保存所有图像。在获得所有图像之后,我们可以使用OCR Space提取文本数据。这是一个简短的代码段:
import requests
def ocr_space_file(filename, overlay=False, api_key='api_key', language='eng'):
payload = {'isOverlayRequired': overlay,
'apikey': api_key,
'language': language,
}
with open(filename, 'rb') as f:
r = requests.post('https://api.ocr.space/parse/image',
files={filename: f},
data=payload,
)
return r.content.decode()
e = ocr_space_file(filename='1.png')
print(e) # prints JSON
1.png:
来自ocr.space的JSON响应:
{"ParsedResults":[{"TextOverlay":{"Lines":[],"HasOverlay":false,"Message":"Text overlay is not provided as it is not requested"},"TextOrientation":"0","FileParseExitCode":1,"ParsedText":"RS 0',85 \r\n","ErrorMessage":"","ErrorDetails":""}],"OCRExitCode":1,"IsErroredOnProcessing":false,"ProcessingTimeInMilliseconds":"1996","SearchablePDFURL":"Searchable PDF not generated as it was not requested."}
它给我们"ParsedText" : "RS 0',85 \r\n"
。