【问题标题】:Python3 scraper. Doesn't parse the xpath till the endPython3 刮刀。直到最后才解析 xpath
【发布时间】:2016-04-28 20:14:53
【问题描述】:

我正在使用 lxml.html 模块

from lxml import html   

page = html.parse('http://directory.ccnecommunity.org/reports/rptAccreditedPrograms_New.asp?sort=institution')

# print(page.content)

unis = page.xpath('//tr/td[@valign="top" and @style="width: 50%;padding-right:15px"]/h3/text()')

print(unis.__len__())

with open('workfile.txt', 'w') as f:
    for uni in unis:
        f.write(uni + '\n')

这里的网站 (http://directory.ccnecommunity.org/reports/rptAccreditedPrograms_New.asp?sort=institution#Z) 到处都是大学。

问题在于它解析到字母“H”(244 unis)。 我不明白为什么,因为我看到它解析所有的 HTML 直到最后。

我还记录了我自己,244 不是列表的限制或 python3 中的任何内容。

【问题讨论】:

  • 考虑使用requestsbeautifulsoup4 ?
  • 同样,正如我所说,它解析 HTML 直到最后。所以问题不在于我使用的请求函数。

标签: python python-3.x web-scraping web-crawler


【解决方案1】:

那个 HTML 页面根本就不是 HTML,它完全被破坏了。但以下将做你想要的。它使用BeautifulSoup 解析器。

from lxml.html.soupparser import parse
import urllib

url = 'http://directory.ccnecommunity.org/reports/rptAccreditedPrograms_New.asp?sort=institution'
page = parse(urllib.request.urlopen(url))
unis = page.xpath('//tr/td[@valign="top" and @style="width: 50%;padding-right:15px"]/h3/text()')

请参阅http://lxml.de/lxmlhtml.html#really-broken-pages 了解更多信息。

【讨论】:

  • 是python3的吗?原因 无法识别 urlopen 函数。
  • 抱歉,使用 Python 2 测试过。对于 Python 3,您需要添加 request。答案已更新。但请注意,您可能会遇到 lxml 的另一个问题:NameError: name 'unichr' is not defined 这在以后的 lxml 版本中已修复(请参阅 lxml.de/api/lxml.html.soupparser-pysrc.html 以供参考)。
  • 顺便说一句,为了让您的 XPath 表达式减少对格式的依赖,也许您应该改用 //tr/td/h3[following-sibling::br]/text()
  • 或模仿 Mad Matts 解决方案,使用 //tr/td/h3/text()[string-length(normalize-space(.))>0]
【解决方案2】:

对于网络抓取,我建议您使用BeautifulSoup 4 使用 bs4 很容易做到这一点:

from bs4 import BeautifulSoup
import urllib.request

universities = []
result = urllib.request.urlopen('http://directory.ccnecommunity.org/reports/rptAccreditedPrograms_New.asp?sort=institution#Z')

soup = BeautifulSoup(result.read(),'html.parser')

table = soup.find_all(lambda tag: tag.name=='table')
for t in table:
    rows = t.find_all(lambda tag: tag.name=='tr')
    for r in rows:
        # there are also the A-Z headers -> check length
        # there are also empty headers -> check isspace()
        headers = r.find_all(lambda tag: tag.name=='h3' and tag.text.isspace()==False and len(tag.text.strip()) > 2)
        for h in headers:
            universities.append(h.text)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2014-03-01
    • 2013-02-21
    • 1970-01-01
    • 2023-03-11
    • 2019-09-23
    相关资源
    最近更新 更多