Skip to main content
 首页 » 编程设计

python之在 b> 标签之间的 p> 标签内抓取文本加上正则表达式问题

2024年10月17日29daizhj

好的,我已经非常接近了,需要帮助才能越过终点线。我有两段文本想用 Scrapy 抓取。格式如下:

<html> 
  <div id="product-description"> 
    <p> 
      Blah blah blah text text text reads: 874620. more text text. 
      <br> 
      <br> 
      <b>Brand:</b> 
      " Nintendo" 
      <br> 
      <b>Condition:</b> 
      " Good" 
    </p> 
  </div> 
</html> 

到目前为止,我只能获取粗体标题(品牌:、条件:),而不是我真正想要的文本(任天堂、好)。与正则表达式类似,我只抓取“reads:”而不是紧随其后的字符串,这就是我想要的 (874620)。这是我所在的位置:

response.xpath('//div[@id="product-description"]//p/b').extract_first() 
 
response.xpath('//div[@id="product-description"]//p').re(r'reads.*') 

请您参考如下方法:

您可以提取 <p> 的全文标记然后运行正则表达式从中提取相关信息

示例代码:

import re 
from scrapy.selector import Selector 
 
html = '''<html> 
  <div id="product-description"> 
    <p> 
      Blah blah blah text text text reads: 874620. more text text. 
      <br> 
      <br> 
      <b>Brand:</b> 
      " Nintendo" 
      <br> 
      <b>Condition:</b> 
      " Good" 
    </p> 
  </div> 
</html>''' 
 
extracted_text = Selector(text=html).xpath('//div[@id="product-description"]//p//text()').extract() 
text = u''.join(extracted_text) 
 
regex = r'reads:\s*(?P<reads>\d+).*Brand:\s*" (?P<brand>\w+)".*Condition:\s*" (?P<condition>\w+)"' 
results = re.search(regex, text, flags=re.DOTALL).groupdict() 
 
results['reads'] = int(results['reads']) 
print(results) 

此代码输出:

{'reads': 874620, 'brand': u'Nintendo', 'condition': u'Good'} 

更新:

让我们看看这段代码做了什么:

xpath

首先,extracted_text获取 <p> 中的所有文本使用 xpath 的标记 //div[@id="product-description"]//p//text() 这个 xpath 意味着:

  • 给我所有的 id 属性匹配的 div “产品描述”
  • 给我上面div里面的所有p标签
  • 从这些 p 标签中获取文本

注意://而不是 /意味着在搜索标签时也包括 child 的 child 和他们的 child 等等。

运行此 xpath 返回 <p> 内标签的每个文本的字符串列表我们找到的标签。

在 xpath 之后,我们使用 u''.join(extracted_text) 将这个列表连接成大字符串.

获得我们想要的全文后,我们可以运行正则表达式从中提取相关数据。

正则表达式

让我们尝试分解正则表达式,看看它的含义:

reads:\s*(?P<reads>\d+).*Brand:\s*" (?P<brand>\w+)".*Condition:\s*" (?P<condition>\w+)"

reads:\s*(?P<reads>\d+) - 给我找一个以 reads: 开头的字符串.后跟零个或多个空格 \s*并创建一个名为 reads 的匹配组,其中包含 \d+表示一位或多位数字。

.*Brand:\s*" (?P<brand>\w+)" - 上面后面跟着零个或多个字符(任何字符),字符串Brand:又一次\s*零个或多个空格后跟双引号和单空格 " .在此之后创建另一个名为 brand 的组,其中包含 \w+表示一个或多个字母数字字母。

.*Condition:\s*" (?P<condition>\w+)" - 这个和上面第二部分一样,为condition

创建匹配组

正则表达式使用标志 DOTALL 执行这意味着 . char 匹配所有字符(包括换行符),因为我们的匹配是跨多行的。

运行上述正则表达式后,我们提取 3 个匹配组并将读取匹配从字符串转换为 int。

我把这个例子上传到here其中包含详细信息及其交互性,因此您可以自己尝试。