请帮我入门lxml

3 投票
2 回答
1677 浏览
提问于 2025-04-16 16:14

我正在学习Python,觉得《Learn Python the Hard Way》、《A Byte of Python》和《Head First Python》这些书都非常不错。不过,现在我想开始一个“真正”的项目,使用lxml让我感觉自己完全是个菜鸟。

我想做的事情(目标)

我想解析一个关于政治的新闻网站的文章。

网址是 http://politiken.dk/politik/

最终的项目应该:

  • 1) 每天(也许每小时)访问上面的URL。
  • 2) 对于每篇相关的文章,我想把它的URL保存到数据库里。相关的文章在一个 <div class="w460 section_forside sec-forside"> 中。有些元素有图片,有些没有。

我想保存以下内容:

  • a - 标题 (<h1 class="top-art-header fs-26">)
  • b - 副标题 (<p class="subheader-art">)
  • c - 如果元素有对应的图片,那么保存“alt”或“title”属性。

  • 3) 访问每个相关的URL,抓取文章的正文并保存到数据库。

  • 4) 如果相关的URL已经在数据库中,就跳过这个URL(上面定义的相关文章总是最新发布的10篇)。

期望的结果是一个数据库表,字段包括:

  • art.i) ID
  • art.ii) URL
  • art.iii) 标题
  • art.iiii) 副标题
  • art.iiiii) 图片alt
  • art.iiiiii) 文章正文。
  • art.iiiiiii) 日期和时间(在 <span class="date tr-upper m-top-2"> 中的字符串)。

以上就是我希望得到帮助的内容。由于屏幕抓取并不总是友好的,我想解释一下我为什么想这么做

基本上,我想挖掘数据,看看议员或政党的出现频率。我不会重新发布这些文章,也不会出售数据之类的(我没有检查我的做法是否合法,但希望并认为应该是合法的)。

我想象中有一个政治家表和一个政党表。

对于每个政治家,我会有:

  • pol.i) ID
  • pol.ii) 名字
  • pol.iii) 姓氏
  • pol.iiii) 政党

对于每个政党,我会有:

  • party.i) ID
  • party.ii) 正确名称
  • party.iii) 常用名称
  • party.iiii) 缩写

我想对几个丹麦的新闻网站做这个,然后分析是否某个报纸偏向某些政治家/政党——简单来说就是根据提及次数来判断。

这也是我需要帮助的地方——但一步一步来:-)

之后我想探索NLTK和情感挖掘的可能性。

我想看看这是否能变成一个政治学/新闻学的博士项目。

这基本上就是我现在的情况(也就是没什么)

我真的很难理解lxml、元素的概念、不同的解析方式等等。当然,我读过教程,但还是很困惑。

import lxml.html

url = "http://politiken.dk/politik/"
root = lxml.html.parse(url).getroot()
# this should retur return all the relevant elements
# does not work:
#relevant = root.cssselect("divi.w460 section_forside sec-forside") # the class has spaces in the name - but I can't seem to escape them?

# this will return all the linked artikles headlines
artikler = root.cssselect("h1.top-art-header")

# narrowing down, we use the same call to get just the URLs of the articles that we have already retrieved
# theese urls we will later mine, and subsequently skip
retrived_urls=[]
for a in root.cssselect("h1.top-art-header a"):
    retrived_urls.append(a)
# this works. 

我希望从回答中得到什么

首先,只要你不骂我(这很糟糕),我就会很高兴。

  • 但我真正希望的是能有一个简单易懂的lxml工作原理的解释。如果我知道该用什么工具来完成上述任务,那我就能更轻松地“深入lxml”。也许是因为我注意力不集中,现在读一些超出我理解能力的内容让我感到失望,我甚至不确定自己是否在找对地方。
  • 如果你能提供一些适合某些任务的示例代码,那就太好了。我希望把这个项目变成博士项目,但我确信这种事情已经做过无数次了?如果是这样,我的经验是向他人学习是变得更聪明的好方法。
  • 如果你觉得我应该放弃lxml,使用比如scrapy或html5lib,请直接告诉我:-) 我开始研究html5lib,因为Drew Conway在一篇关于政治科学家的Python工具的博客中提到过,但我找不到入门级的材料。另外,lxml是scraperwiki推荐的。至于scrapy,这可能是最好的解决方案,但我担心scrapy太像一个框架——如果你知道自己在做什么并想快速完成,那确实很好,但可能不是学习Python魔法的最佳方式。
  • 我计划使用关系数据库,但如果你认为比如mongo会有优势,我会改变我的计划。
  • 由于我无法在Python 3.1中安装lxml,所以我正在使用2.6。如果这样做不对,请告诉我。

时间框架

我在stackoverflow上问了很多初学者的问题。多得让我不敢自豪。但由于我有一份全职工作,我似乎总是无法沉浸在代码中,吸收我渴望的技能。我希望这是一个我可以定期回来看并更新我所学内容的问题/答案,这也意味着这个问题可能会保持活跃很长时间。但我会对每个我可能幸运地收到的回答进行评论,并不断更新“我得到了什么”部分。

目前我觉得我可能咬得太多了——所以现在我要回去看《Head First Python》和《Learn Python the Hard Way》。

最后的话

如果你能看到这里——你真棒——即使你不回答问题。你已经读了很多简单、困惑和愚蠢的问题(我为问这些问题感到自豪,所以别争论)。你应该喝杯咖啡,抽根烟,祝贺自己:-)

节日快乐(在丹麦,我们庆祝复活节,现在阳光明媚,就像《低俗小说》中塞缪尔·杰克逊的钱包一样闪亮)。

编辑

看起来BeautifulSoup是个不错的选择。不过开发者表示,如果我想使用Python3,BeautifulSoup并不是一个好选择。但根据这个链接,我更倾向于使用Python3(不过不是特别强烈)。

我还发现《Dive Into Python 3》中有一个关于lxml的章节。我也会去看看。

2 个回答

2

现在,lxml绝对是解析HTML的首选工具。

这里有一份lxml的速查表,可以帮助你找到很多答案:

http://scraperwiki.com/docs/contrib/python_lxml_cheat_sheet/

你写的那段代码可以直接使用,并且可以在ScraperWiki的编辑窗口中运行。 http://scraperwiki.com/scrapers/andreas_stackoverflow_example/edit/

通常,一个链接的格式是: <a href="链接">标题</a>

在用lxml解析后,你可以通过以下方式获取链接: a.attrib.get("href") 而获取文本则可以用 a.text

不过,在这个特定的情况下,链接的格式是: <a href="链接"> <span> </span> 标题</a> 所以,a.text的值只代表了'<a href="链接">'和第一个'<span>'之间的字符。

但是你可以使用以下代码,通过递归遍历子元素(在这个例子中是<span>)来简化处理:

def flatten(el):           
    result = [ (el.text or "") ]
    for sel in el:
        result.append(flatten(sel))
        result.append(sel.tail or "")
    return "".join(result)
3

这段内容有点多,或许你可以把问题拆分成几个小问题。

关于lxml,这里有一些示例。官方文档也很不错,花点时间去看看这些例子吧。而且他们的邮件列表非常活跃。

关于BeautifulSoup,lxml在性能上更高效,而且根据我的经验,它能更好地处理那些有问题的HTML。缺点是lxml依赖于C语言的库,所以安装起来可能会比较麻烦。

撰写回答