我是使用python解析html的新手,我遇到了麻烦。我正在尝试编写一个简短的脚本,每天从网站上获取一个数字。但是,代码不是返回我想要的数字,而是返回None
。
以下网页显示每天穿越特定区域的自行车数量:http://eco-public.com/public2/?id=100023038。我正在尝试编写一个简短的python脚本来记录乘坐“昨天”的自行车数量(这是每天不同的数字,通常介于500和1,500之间)。当我检查网页的那个元素时,我发现它的xpath是://*[@id="region-lastDay"]/div/p[2]/text()
。但是,当我尝试使用以下代码返回数字时,它会返回值None
。
import lxml.html as lh
import urllib2
doc = lh.parse(urlopen('http://eco-public.com/public2/?id=100023038'))
daily = doc.xpath('//*[@id="region-lastDay"]')
for i in daily:
print i.text
我做错了什么?
答案 0 :(得分:0)
如果您查看浏览器对该网址的原始请求(例如,使用Chrome或Firefox中的开发者工具,或只打印出urlopen(...).read()
的值),您会看到region-lastDay
元素看起来像这样:
<!-- Key Numbers -->
<div class="row" id="keyrow">
<div id="region-total" class="col-xs-12 col-sm-6 col-md-4"></div>
<div id="region-lastDay" class="col-xs-12 col-sm-6 col-md-4" ></div>
</div>
它确实是空的,因为在初始页面加载后使用返回JSON的AJAX调用(通过Chrome的开发人员工具 - &gt;网络选项卡观察)填充元素:
因此,您需要使用lxml
来解析来自用于AJAX调用的URL的响应,而不是使用json
:
从JSON中抓取最终元素,如下所示:
>>> import urllib.request
>>> import json
>>> response = urllib.request.urlopen("http://www.eco-public.com/api/h7q239dd/data/periode/100023038?begin=20150623&end=20150801&step=4")
>>> data = json.loads(response.read().decode('utf8'))
>>> data[-1]
{'comptage': 695, 'timestamp': 1438380000000, 'date': '2015-08-01 00:00:00.0'}
您还可能需要调整网址中的start
和end
参数来获取其他日期的数据。
答案 1 :(得分:0)
html代码中div
为空。
<div id="region-lastDay" class="col-xs-12 col-sm-6 col-md-4" ></div>
它充满了javascript。 Javascript部分无法由lxml
处理。你需要能够处理javascript部分的包(例如selenium
)。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Firefox() # OR Chrome() / PhantomJS() / ...
driver.get('http://eco-public.com/public2/?id=100023038')
xpath = '//*[@id="region-lastDay"]/div'
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, xpath)))
daily = driver.find_elements_by_xpath(xpath)
for i in daily:
print i.text
# driver.quit()
答案 2 :(得分:0)
我知道这是一个老问题;但是,我在加载Javascript生成的页面时遇到了问题,因为lxml在JS加载之前抓取数据并且我找到了解决方案。
此解决方案将要求您使用这些导入:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from lxml import html
和此代码等待页面呈现
#Take this class for granted.Just use result of rendering.
class Render(QWebPage):
def __init__(self, url):
self.app = QApplication(sys.argv)
QWebPage.__init__(self)
self.loadFinished.connect(self._loadFinished)
self.mainFrame().load(QUrl(url))
self.app.exec_()
def _loadFinished(self, result):
self.frame = self.mainFrame()
self.app.quit()
现在,一旦你有了这个,你就可以这样开始拼抢:
url = 'http://pycoders.com/archive/'
r = Render(url)
result = r.frame.toHtml()
#This step is important.Converting QString to Ascii for lxml to process
archive_links = html.fromstring(str(result.toAscii()))
print archive_links
使用Render类,您可以加载页面并将其转换为Ascii for lxml。 我有“print archive_links”,所以你可以看到它返回的结构,你不需要这个。
现在要收集您收集的信息,您可以使用lxml。
#Now using correct Xpath we are fetching URL of archives
archive_links = tree.xpath('//divass="campaign"]/a/@href')
print archive_links
所有这些代码从上到下组合在一起,将为您提供一个包含JS生成元素的加载页面,并允许您使用lxml抓取它们。