用Python中的Scrapy解析时保留换行符
我写了一个从页面中提取文本的Scrapy蜘蛛。蜘蛛在许多页面上解析并正确输出,但被少数几页丢弃。我试图在文档中保留换行符和格式。如http://www.state.gov/r/pa/prs/dpb/2011/04/160298.htm页面格式正确像这样:用Python中的Scrapy解析时保留换行符
2011年4月7日
马克C.碳粉
下午2时03分EDT
MR。 TONER:大家下午好。顶部有几件事, ,然后我会回答你的问题。我们谴责以最强烈的措辞攻击以色列南部无辜平民 以及从加沙持续发射的火箭弹 。正如我们多次重申的那样, 没有任何理由针对无辜平民, 和那些对这些恐怖行为负责的人应该对 负责。我们特别关注的报告显示 在对平民 的袭击中使用了先进的反坦克武器,并重申所有国家都有义务根据联合国安理会决议防止非法贩运军火弹药 。也只是一个简短的声明 -
问题:我们可以停留在那一秒钟吗?
MR。 TONER:是的。来吧,马特。
问题:很显然,这是一辆校车的目标。那 会增加你的愤怒吗?
MR。 TONER:好吧,对无辜平民的任何袭击都是可恶的,但是攻击的性质当然尤其如此。
虽然像http://www.state.gov/r/pa/prs/dpb/2009/04/121223.htm页有这样的输出没有换行符:
2009年4月2日
罗伯特·伍德·
上午11时53分EDTMR。伍德:大家早上好。大约在早上,我认为它只是 。欢迎来到简报。我没有什么, 所以,“先生。”问:朝鲜人已经搬运加油车,或 无论如何,靠近现场。他们可能或可能不会加装这种导弹。你现在对 北朝鲜人有什么智慧?伍德:好吧,马特,我不打算评论,你知道,情报事宜。但让我再说一遍,我们呼吁北方停止发射任何类型的导弹。这将是 适得其反。它的挑衅。这进一步加剧了该地区的紧张局势。我们希望看到北方回到六方框架,并专注于无核化。是的。问:日本也有 表示他们将要求在安理会召开紧急会议 委员会,你知道,应该这样做发射继续。你是不是也在寻找这种东西?伍德:好吧,让我们看看这个测试 是否发生。我们当然希望它没有。再次呼吁北方 不要这样做。但是当然,我们会,“如果这个测试继续进行,我们将与我们的盟友进行讨论” 。
我正在使用的代码如下:
def parse_item(self, response):
self.log('Hi, this is an item page! %s' % response.url)
hxs = HtmlXPathSelector(response)
speaker = hxs.select("//span[contains(@class, 'official_s_name')]") #gets the speaker
speaker = speaker.select('string()').extract()[0] #extracts speaker text
date = hxs.select('//*[@id="date_long"]') #gets the date
date = date.select('string()').extract()[0] #extracts the date
content = hxs.select('//*[@id="centerblock"]') #gets the content
content = content.select('string()').extract()[0] #extracts the content
texts = "%s\n\n%s\n\n%s" % (date, speaker, content) #puts everything together in a string
filename = ("/path/StateDailyBriefing-" + '%s' ".txt") % (date) #creates a file using the date
#opens the file defined above and writes 'texts' using utf-8
with codecs.open(filename, 'w', encoding='utf-8') as output:
output.write(texts)
我认为他们的问题出在网页的HTML的格式。在错误输出文本的页面上,段落之间用<br> <p></p>
分隔,而在正确输出的页面上,段落包含在<p align="left" dir="ltr">
之内。所以,虽然我已经确定了这一点,但我不确定如何以正确的形式持续输出所有内容。
的问题是,当你得到text()
或string()
,<br>
标签不会转换为新行。
解决方法 - 做XPath表达式之前更换<br>
标签。代码:
response = response.replace(body=response.body.replace('<br />', '\n'))
hxs = HtmlXPathSelector(response)
让我给些建议,如果你知道,世界上只有一个节点,你可以使用text()
代替string()
:
date = hxs.select('//*[@id="date_long"]/text()').extract()[0]
试试这个XPath:
//*[@id="centerblock"]//text()
你将不能够只是'“” .join(content)'因为文本不包含换行符,并且''\ n'.join(content)'不仅会拆分段落,而且还会拆分'...'。 – reclosedev 2012-01-05 20:05:56
这可行,但由于要求加入列表@reclosedev有一个更清洁和更简单的方法。不过谢谢你。 – user1074057 2012-01-05 20:50:49
我建议使用正则表达式替换普通字符串以减少限制:'response = response.replace(body = re.sub(r“
”,“\ n”,response.body))' – Guillaume 2016-10-28 11:57:03