刚刚介绍给Scrapy。已经完成了基础教程,但觉得我不太了解如何使用它。
我需要解析的简单案例就像:
BASIC CASE
<li>
<b>Descriptive Title</b>
<br>
The_first_paragraph_of_text
<p>Second paragraphs of text</p>
...
<p>Nth Paragraph of text</p>
</li>
我想要做的是生成一个包含两列的数据库记录,&#34; title&#34;和&#34; body_text&#34;。标题来自“描述性标题”&#39;而body_text来自于获取所有文本段落并连接成一个文本块。
我写了一些像
这样简单的东西"""pulls out the Descriptive Title and all the <p>-wrapped paragraphs but misses the first paragraph (which isn't wrapped in a <p>"""
for sel in response.xpath("//li"):
b = sel.xpath('b').extract()
print "b = {0}\n".format(b)
for p in sel.xpath('p'):
paragraph = p.xpath('text()').extract()
print"\n{0}".format(paragraph)
但这并没有抓住第一段,只有第二段及以后的段落。而且,它对<li>
html块的变体不稳健。
在一个变体中,第一段有时用斜体字包裹。
ITALICS COMPLICATION
<li>
<b>Descriptive Title</b>
<br>
<i>Occasionally The_first_paragraph_of_text is in italics</i>
<p>Second paragraphs of text</p>
...
<p>Nth Paragraph of text</p>
</li>
在另一个变体中,有时<li>
嵌入在某些段落块中。
SUB LIST-ITEM COMPLICATION
<li>
<b>Descriptive Title</b>
<br>
<i>Occasionally The_first_paragraph_of_text is in italics</i>
<p>Second paragraphs of text</p>
<p>Sometimes paragraphs will have lists inside them
<li>idea 1</li>
<li>idea 2</li>
<li>idea N</li>
</p>
<p>Nth Paragraph of text</p>
</li>
我怀疑我并没有在&#34; scrapythonic&#34;中消化html文件。办法。什么是正确的方法来编写更强大的选择器来提取我想要的东西?
答案 0 :(得分:1)
更多的xpath问题而不是scrapy问题
如果您的标题始终位于第一个元素中,则为<b>
标记
它很容易sel.xpath('b[1]/text()')
。
如果我是你,我会添加一些严格的断言
使它失败而不是废弃错误的标题文本
因为<b>
标记通常可以扮演其他角色
尝试:
title, = sel.xpath('*[1][self::b and count(node())=count(text())]')
title = u'\n'.join(sel.xpath('text()'))
其内容如下(括号中的断言):
必须存在一个且只有一个标签(由title, =
声明)
这是第一个标签(由[1]
声明)
并且是<b>
(由self::b
声明)
并且只有文本节点(由count(text())=count(node())
声明)
对于正文,
你将不得不习惯使用html进行格式化
除非你正在抓一个网站
它非常简单地格式化其主要内容
(例如安排了<p>
标签)。
您可以按文档顺序获取所有文本后代:
sel.xpath('.//text()')
但是,<script>
和<style>
标记可能会显示不需要的文字;
你不希望你的正文用javascript / css乱码填充
您可以通过以下方式阻止它们被选中:
sel.xpath('.//text()[not(parent::script or parent::style)]')
然后,您可能希望将提取的文本与u'\n'.join()
这将解决您的问题,但不会处理所有不需要的标签
玩lxml.html.clean.Cleaner(style=True)
左右
(记录在此http://lxml.de/lxmlhtml.html#cleaning-up-html)
并考虑找一个将html呈现为文本的库。