http://blog.ez2learn.com/2008/10/05/python-is-the-best-choice-to-grab-web/
以我抓網頁的經驗來講,Twisted + lxml是我目前用過最好用的工具組合
我有寫一個函式庫是架構在那之上的
http://webchuan.ez2learn.com/
它的設計是用piple line的概念,可以同時開很多管線來抓網頁,速度會很快
http://webchuan.ez2learn.com/wiki/DesignOfWebChuan
這有幾個例子
http://webchuan.ez2learn.com/wiki/Examples/GetPageTitle
http://webchuan.ez2learn.com/wiki/Examples/DownloadPhotos
不過如果是很少的資料,直接用twisted + lxml開發起來反而輕鬆
因為twisted的deferred機制已經很棒了,而且反正資料也一下子就抓完了,沒必要寫多好
我的webchuan因為後來也沒有遇到需要抓比較大網站,所以我自己也沒有在用,可能會有一些bug
有興趣可以參考看看,程式寫沒有很好,不過我想設計的概念應該是對的
甚至我想說可以做出GUI界面,讓抓網頁拉一拉元素接在一起構成pipeline就可以跑
以上
Victor Lin.
可以參考我寫的
http://blog.ez2learn.com/2008/10/05/python-is-the-best-choice-to-grab-web/
以我抓網頁的經驗來講,Twisted + lxml是我目前用過最好用的工具組合
我有寫一個函式庫是架構在那之上的
http://webchuan.ez2learn.com/
它的設計是用piple line的概念,可以同時開很多管線來抓網頁,速度會很快
http://webchuan.ez2learn.com/wiki/DesignOfWebChuan
這有幾個例子
http://webchuan.ez2learn.com/wiki/Examples/GetPageTitle
http://webchuan.ez2learn.com/wiki/Examples/DownloadPhotos
不過如果是很少的資料,直接用twisted + lxml開發起來反而輕鬆
因為twisted的deferred機制已經很棒了,而且反正資料也一下子就抓完了,沒必要寫多好
On 3月2日, 下午10时49分, Victor Lin <Borns...@gmail.com> wrote:
> 可以參考我寫的
>
> http://blog.ez2learn.com/2008/10/05/python-is-the-best-choice-to-grab...
>
> 以我抓網頁的經驗來講,Twisted + lxml是我目前用過最好用的工具組合
> 我有寫一個函式庫是架構在那之上的http://webchuan.ez2learn.com/
>
> 它的設計是用piple line的概念,可以同時開很多管線來抓網頁,速度會很快http://webchuan.ez2learn.com/wiki/DesignOfWebChuan
>
> 這有幾個例子http://webchuan.ez2learn.com/wiki/Examples/GetPageTitlehttp://webchuan.ez2learn.com/wiki/Examples/DownloadPhotos
d = deferredToThread(parseBigComplexHtml, html)
它就會被丟到thread pool完成了再回傳過來
雖然複雜,但有它的好處在
On 3月3日, 上午9時59分, Heroboy <yangwei...@gmail.com> wrote:
> 我觉得Twisted + lxml太复杂太庞大了吧。
> 我的经验是用python读取某些目录的页面,生成下载地址,让专业的下载工具去下载。那样就不用python去关心类似断线续传诸如此类的问题了。
>
> 2009/3/2 Victor Lin <Borns...@gmail.com>
>
> > 可以參考我寫的
>
> >http://blog.ez2learn.com/2008/10/05/python-is-the-best-choice-to-grab...
<div id="foo">blah...</div>
這樣來說,正規表示法就可以做得很好,但是就如果是要靠上下文才能找到目標的內容,例如
<h1 id="title">...</h1>
<div>...</div>
正規表示法就可頭大了,可能要先找到附近可以辯識的目標,然後再想辦法找到相對的關系,但是lxml用xpath就不會有這問題,不管是子孫、兄弟節
點,都可以用語法來表達並且找到
BeautifulSoup雖然也不錯,但是它的find之類函數實在是太沒效率了,我之前開發過一個抓amazon商品資料的程式,就是用
beautifulsoup,我發現CPU使用率都是佔滿的,不像我預期的那樣,都在等網路IO,而是都在等CPU,我使用profile下去跑,發現
八九成的時間都落在soup的find上面,他的find實在是很暴力,為了效能考量,我後來就改用lxml,不只效能上改進太多了,而且我發現用
xpath來抓標籤,比用一個一個find再用判斷之類的來得容易和輕楚,給個例子,我有抓過台灣的股價報表網頁,有用beautifulsoup寫過
的版本,和lxml寫過的版本,可以比較看看
# beautiful soup
def parsePrice(html):
"""after 95/12/31
"""
soup = BeautifulSoup(html.decode('cp950', 'ignore'))
# <table id='contentTable' cellpadding='0' cellspacing='1'
border='0' style='width:100%;'>
table = soup.find('table', {'id': 'contentTable', 'cellpadding':
'0', 'cellspacing': '1', 'border': '0', 'style': 'width:100%;'})
if table:
trList = table.findAll('tr')
priceList = []
for tr in trList:
tdList = tr.findAll('td')
#print fontList
valueList = []
for td in tdList:
content = unicode(td.contents[0]) if td.contents else
''
content = content.replace(u',', '').replace(u'⊙',
'').replace(u'⊕', '').strip()
valueList.append(content)
#print len(valueList), valueList
if len(valueList) == 17:
id = str(valueList[0])
name = valueList[1]
close = float(valueList[2])
open = float(valueList[4])
high = float(valueList[5])
low = float(valueList[6])
volume = int(valueList[8].replace(',', ''))
stockPrice = {'id': id,
'name': name,
'volume': volume,
'open': open,
'close': close,
'high': high,
'low': low
}
if not stockPrice['id'].startswith('0') and len
(stockPrice['id']) == 4:
try:
stockPrice['id'] = int(stockPrice['id'])
priceList.append(stockPrice)
#print stockPrice
except ValueError:
pass
return priceList
return None
# lxml
def parsePriceFaster(html):
"""after 95/12/31, faster version, using lxml
"""
parser = etree.HTMLParser()
tree = etree.parse(StringIO.StringIO(html.decode('cp950',
'ignore')), parser)
trList = tree.xpath("/descendant::table[@id='contentTable']//tr")
if trList:
def getPriceMap(tr):
tdList = tr.xpath("td")
#print etree.tostring(tr, pretty_print=True)
if len(tdList) != 17:
return None
id = strip(tdList[0])
name = unicode(strip(tdList[1]).replace(' ', ''))
close = float(strip(tdList[2]))
open = float(strip(tdList[4]))
high = float(strip(tdList[5]))
low = float(strip(tdList[6]))
volume = int(strip(tdList[8]))
if not id.startswith('0') and len(id) == 4:
try:
id = int(id)
except ValueError:
return None
else:
return None
stockPrice = {
'id': id,
'name': name,
'volume': volume,
'open': open,
'close': close,
'high': high,
'low': low
}
#print stockPrice
return stockPrice
resultList = [getPriceMap(tr) for tr in trList]
return filter(lambda x: x, resultList)
return None
同樣是找tr,xpath一句話就解決了
On 3月3日, 上午10時16分, Li Feng <nemoking...@gmail.com> wrote:
> 我感觉还是像BeautifulSoup之类的对html, xml进行解析的工具比较方便。
> 正则表达式表达的意思比较隐讳,没有比较清晰的语意。虽然可能会快些。
>
> Li Feng
> blog:http://okidogi.yo2.cn
>
> 2009/3/3 小将 <withw...@gmail.com>
>
> > 其实我个人认为,主要的地方会是在*抓*这个过程,而不是*信息抽取*的过程。
> > 主要是多线程,还有一些智能化。比如说只给出首页,spider就会抓到内部所有的链接,再抓到内容。
> > 抓到内容之后,信息抽取用正取表达式,来的会比其它的更快一些。写起来也方便一些。
>
> > On 3月2日, 下午10时49分, Victor Lin <Borns...@gmail.com> wrote:
> > > 可以參考我寫的
>
> > >http://blog.ez2learn.com/2008/10/05/python-is-the-best-choice-to-grab...
>
> > > 以我抓網頁的經驗來講,Twisted + lxml是我目前用過最好用的工具組合
> > > 我有寫一個函式庫是架構在那之上的http://webchuan.ez2learn.com/
>
> > > 它的設計是用piple line的概念,可以同時開很多管線來抓網頁,速度會很快
> >http://webchuan.ez2learn.com/wiki/DesignOfWebChuan
>
> > > 這有幾個例子
> >http://webchuan.ez2learn.com/wiki/Examples/GetPageTitlehttp://webchua...
On 3月3日, 上午11时40分, Heroboy <yangwei...@gmail.com> wrote:
> 你要是想写个框架写个强大且通用的东西的话,当然可以竭尽所能用最好的最有效率的。不过已经有现成的http://linux.duke.edu/projects/urlgrabber/了。
> 在网上看到一篇小说,或者套图之类的,临时写个程序,难道还要很麻烦的安装2个二进制包的Twisted+lxml?内置的正则表达式甚至是string.fi-nd,或者是只有一个py文件的BeautifulSoup才是最方便的。
> 要是没有python的话,用javascript都可以写一个,顺便还可以使用浏览器强大的dom,http://userscripts.org/scripts/show/37453。
> 我觉得这种程序最重要的就是,当Ctrl+break或者关机了,第二天能接着下载。这也是我推荐用python来生成下载列表,而让其它下载软件来下载的原因-。否则,python写起来不但十分的麻烦,而且不那么绿色。
>
> 2009/3/3 Victor Lin <Borns...@gmail.com>
> > > > > > 最好是多线程的,采集时间不要太长。- 隐藏被引用文字 -
>
> - 显示引用的文字 -
如果只要link和name的话,BeautifulSoup就足够啦。
2009/3/2 python <malin...@gmail.com>:
--
Xunhao Li
A USTC Alumnus
Sent from: Edmonton Ab Canada.
顶 wget,
如果不是像上次某人那样坚持不要别人的任何模块自己写纯 python,
简单用个 wget 命令行就足够了(XP 可以装 msys)
是说 msys 省事点,不会再要啥了还临时装,
而且 bash 比 cmd 省事点。
On 3月2日, 下午11时20分, LaiYonghao <lanpha...@gmail.com> wrote:
> 谢谢分享,写得挺好,比你正儿八经写的教程要好,大概是因为我喜欢这种毫不造作的自然语调吧。
>
> 我也写过爬虫,用的是 urllib2 和
> beautifulsoup,用来抓取我的喜欢的网络图片,其实抓取内容是不是自己想要的,可以通过自己写个函数过去注册一下就行了。因为我自己的应用不太健康-,所以就不分享啦。哈哈。
>
> 2009/3/2 Victor Lin <Borns...@gmail.com>
>
>
>
>
>
> > 可以參考我寫的
>
> >http://blog.ez2learn.com/2008/10/05/python-is-the-best-choice-to-grab...
>
> > 以我抓網頁的經驗來講,Twisted + lxml是我目前用過最好用的工具組合
> > 我有寫一個函式庫是架構在那之上的
> >http://webchuan.ez2learn.com/
>
> > 它的設計是用piple line的概念,可以同時開很多管線來抓網頁,速度會很快
> >http://webchuan.ez2learn.com/wiki/DesignOfWebChuan
>
> > 這有幾個例子
> >http://webchuan.ez2learn.com/wiki/Examples/GetPageTitle
> >http://webchuan.ez2learn.com/wiki/Examples/DownloadPhotos
>
> > 不過如果是很少的資料,直接用twisted + lxml開發起來反而輕鬆
> > 因為twisted的deferred機制已經很棒了,而且反正資料也一下子就抓完了,沒必要寫多好
>
> > 我的webchuan因為後來也沒有遇到需要抓比較大網站,所以我自己也沒有在用,可能會有一些bug
> > 有興趣可以參考看看,程式寫沒有很好,不過我想設計的概念應該是對的
> > 甚至我想說可以做出GUI界面,讓抓網頁拉一拉元素接在一起構成pipeline就可以跑
>
> > 以上
>
> > Victor Lin.
>
> > On 3月2日, 下午9時56分, python <malinqi...@gmail.com> wrote:
> > > 只要爬虫就行,小型的。具体要求如下:
> > > 爬http://www.readnovel.com中的所有小说名称和链接地址。
> > > 如小说名称:幻梦千年;小说链接:http://www.readnovel.com/novel/56324.html;最近更新章节:第二十九节
> > > (http://www.readnovel.com/partlist/56324/)只要这三项就可以。
> > > 最好是多线程的,采集时间不要太长。
>
> --
> 赖勇浩的编程私伙局:http://blog.csdn.net/lanphaday- 隐藏被引用文字 -
>
> - 显示引用的文字 -
但是如果不考慮Twisted + lxml需要另外安裝的問題的話,但是用twisted + lxml就算抓簡單的網頁、圖片之類的也是非常輕鬆的
事情,例如圖片好了,用xpath只要這樣寫
imgs = tree.xpath("//img")
for img in imgs:
pass
就一口氣抓完所有圖片,雖然regular也辦得到,但是還得想一下語法,查一下regular語法,如果我們能夠輕鬆地使用牛刀殺雞,為什麼要花更多
時間? 當然牛刀要部署得付出代價,省下來的是寶貴的開發時間,而且我不認為easy_install或是next next...的twisted和
lxml安裝過程會比開發時間還來得長和寶貴,再者用完就丟的程式也不需要管綠不綠色,我不明白綠不綠色對於用完即丟的程式有何重要性可言,為了證明我
所說的,我示範一下如何用牛刀殺雞,下面程式示範如何抓到一個網頁裡的所有圖片,用的正是我所提到的twisted + lxml
import cStringIO
from twisted.internet import reactor
from twisted.web.client import getPage
from twisted.python.util import println
from lxml import etree
def parseHtml(html):
parser = etree.HTMLParser()
tree = etree.parse(cStringIO.StringIO(html), parser)
imgs = tree.xpath("//img")
for img in imgs:
print img.get('src')
reactor.stop()
d = getPage('http://www.google.com.tw')
d.addCallbacks(parseHtml)
d.addErrback(println)
reactor.run()
雖說twisted + lxml是牛刀,但是對於小應用來說會使的話一點都不費力,以上程式用了一兩分鐘就寫好了,xpath 對於像這樣簡單的應用
來說,還是簡單到不行,只要你大概懂xpath,上面的應用連語法都不用查,用regular expression還得查語法,而且還有greedy
的問題,可能忘記加?在後面發現奇怪,怎麼網頁全部抓進來了,才發現忘了加?而beautifulsoup只有簡單的find函數,稍唯再複雜個一點點
就需要額外的羅輯來找tag,當然我不是說beautifulsoup或regular expression不好,只是目的在解決問題,所以對於細節
一點都不在意,twisted綠色與否、lxml綠色與否,一點都不重要,重點在於開發的效率
這只是最簡單的例子,如果你想要某個標籤內的img就好呢? xpath還是一樣輕鬆,只要把上面那行xpath改成
imgs = tree.xpath("//div[@id='foo']//imgs")
那regular expression或是find之類的呢? ... regular expression變得更複雜,你可能要拆成兩段,先找
div抓裡面的字再找imgs
好吧,那再複雜一點呢? 假如如果你只能靠辮識div,再找它的parent,然後再找它的第幾個兄弟來抓到tag怎麼辦? regular
expression會寫眼睛花了,beautiful soup有點小麻煩,但lxml + xpath還是一樣優雅
這裡所說的複雜還算在簡單的範圍內,既然有更優雅的方式,我個人是寧可選擇優雅地揮兩下牛刀就把雞殺了,而不想花任何寶貴的開發時間在無所謂的綠色與否
上,再者twisted + lxml也可以用py2exe打包,這點我有做過,到最後只剩一個資料夾裡面執行檔和一堆libraries,根本沒有安
裝的問題
我想說的是,twisted + lxml是我目前覺得最好用的抓網頁工具組合,並不代表說所有網頁非得用它們來抓不可,但是用它來抓有像我說的這些好
處,如果你不在意安裝那種小問題的話,twisted + lxml絕對是非常好的選擇,當然如果有更好的解決方法我也想知道,或許是我太淺,還有更好
的方法我不知道,或許可以貼上來同樣目的的程式不同的方案解決寫出來會是什麼樣子,可以跟大家分享一下
On 3月3日, 上午11時40分, Heroboy <yangwei...@gmail.com> wrote:
> 你要是想写个框架写个强大且通用的东西的话,当然可以竭尽所能用最好的最有效率的。不过已经有现成的http://linux.duke.edu/projects/urlgrabber/了。
> 在网上看到一篇小说,或者套图之类的,临时写个程序,难道还要很麻烦的安装2个二进制包的Twisted+lxml?内置的正则表达式甚至是string.find,或者是只有一个py文件的BeautifulSoup才是最方便的。
> 要是没有python的话,用javascript都可以写一个,顺便还可以使用浏览器强大的dom,http://userscripts.org/scripts/show/37453。
> 我觉得这种程序最重要的就是,当Ctrl+break或者关机了,第二天能接着下载。这也是我推荐用python来生成下载列表,而让其它下载软件来下载的原因。否则,python写起来不但十分的麻烦,而且不那么绿色。
>
> 2009/3/3 Victor Lin <Borns...@gmail.com>
import urlparse
import cStringIO
from twisted.internet import reactor
from twisted.web.client import getPage
from twisted.python.util import println
from lxml import etree
imgCount = 0
def saveImg(data, name):
global imgCount
print 'Save', name
open(name, 'wb').write(data)
imgCount -= 1
if not imgCount:
reactor.stop()
def parseHtml(html, base):
global imgCount
parser = etree.HTMLParser()
tree = etree.parse(cStringIO.StringIO(html), parser)
imgs = tree.xpath("//img")
imgCount += len(imgs)
for img in imgs:
url = urlparse.urljoin(base, img.get('src'))
name = url.split('/')[-1]
print url
d = getPage(url)
d.addCallback(saveImg, name=name)
url = 'http://www.google.com.tw'
d = getPage(url)
d.addCallback(parseHtml, base=url)
d.addErrback(println)
reactor.run()
> ...
>
> 閱讀更多 >>
我们也做的是抓取,不过没做异常恢复。严格的异常恢复太困难了,需要保存出错
当时的现场。非通用的异常恢复又太多变。
我们将数据的输出封装成了接口,每次运行的时候动态指定接口。向数据库还是
WebService都不困难。
On Mar 3, 2:03 pm, Jiahua Huang <jhuangjia...@gmail.com> wrote:
> 2009/3/3 Leo Jay <python.leo...@gmail.com>:
>
> > wget编译出来就是native的,不需要其它库的。
>
> 是说 msys 省事点,不会再要啥了还临时装,
> 而且 bash 比 cmd 省事点。
如果机器允许装msys,还是这个东西好使。
On Mar 3, 3:20 pm, testisok <testi...@gmail.com> wrote:
> 我写了个应用,可以将整个含有图片的树形目录整个存储/恢复,隐藏地点mysql,可以合作一下,握个抓
>
广告贴?
暈,在哪添加附檔
> ...
>
> 阅读更多 >>