你見過哪些令你瞠目結舌的爬蟲技巧?

瞠目結舌系列:
http://www.zhihu.com/question/38241342


第一條:you-get(Releases · soimort/you-get · GitHub,這裡面有各種發布版本)。什麼,你不知道?想爬取視頻網站的視頻和圖片分享網站的圖片,是不是就得造個輪子寫個爬蟲?No,你只需要:

? pip3 install you-get

能幹什麼呢?我提供幾個例子:


1. 下載優酷視頻

? you-get http://v.youku.com/v_show/id_XMTc1MDQwODMxNg==.html
site: 優酷 (Youku)
title: 麻雀 51
stream:
- format: hd2
container: flv
video-profile: 超清
size: 552.9 MiB (579718488 bytes) # download-with: you-get --format=hd2 [URL]

Downloading 麻雀 51.flv ...
100% (552.9/552.9MB) ├██████████████████████████████████████████████████████████████████████████┤[16/16] 9 MB/s
Merging video parts... Merged into 麻雀 51.mp4

評論區 @xavierskip 提到可以使用-p觀看無廣告的優酷視頻!我在Mac上使用的是mplayer

,安裝和使用方法如下:

? brew install mplayer ? you-get -p /usr/local/Cellar/mplayer/1.3.0/bin/mplayer http://v.youku.com/v_show/id_XMTc1MDQwODMxNg==.html

這樣就可以使用本地播放器播放了


2. B站

? you-get http://www.bilibili.com/video/av6543659/
Site: bilibili.com
Title: 【張繼科】論張繼科的CP是如何被國胖隊手撕的
Type: Flash video (video/x-flv)
Size: 28.2 MiB (29567551 Bytes)

Downloading 【張繼科】論張繼科的CP是如何被國胖隊手撕的.flv ...
100% ( 28.2/ 28.2MB) ├████████████████████████████████████████████████████████████████████████████┤[1/1] 7 MB/s

Downloading 【張繼科】論張繼科的CP是如何被國胖隊手撕的.cmt.xml ...

3. 網易雲音樂

? you-get http://music.163.com/#/song?id=424262521
Site: 163.com
Title: 5. Rolling in the deep
Type: MP3 (audio/mpeg)
Size: 5.86 MiB (6144044 Bytes)

Downloading 5. Rolling in the deep.mp3 ...
100% ( 5.9/ 5.9MB) ├████████████████████████████████████████████████████████████████████████████┤[1/1] 16 MB/s

Saving 5. Rolling in the deep.lrc ...Done.

4. 花瓣畫板

? you-get http://huaban.com/boards/27965679/
Site: 花瓣 (Huaban)
Title: 黑板畫
Type: JPEG Image (image/jpeg)
Size: inf MiB (inf Bytes)

Downloading 595209478.jpeg ...
0.0% ( 0.1/ infMB) ├────────────────────────────────────────────────────────────────────────────┤[1/1] 114 kB/s

Downloading 595209312.jpeg ...
0.0% ( 0.0/ infMB) ├────────────────────────────────────────────────────────────────────────────┤[1/1] 152 kB/s

Downloading 595209225.jpeg ...
0.0% ( 0.1/ infMB) ├────────────────────────────────────────────────────────────────────────────┤[1/1] 344 kB/s

Downloading 595209031.jpeg ...
0.0% ( 0.0/ infMB) ├────────────────────────────────────────────────────────────────────────────┤[1/1] 119 kB/s

Downloading 595208942.jpeg ...
0.0% ( 0.1/ infMB) ├────────────────────────────────────────────────────────────────────────────┤[1/1] 248 kB/s

.... 圖片太多就展示到這裡吧 (?&>?&

支持的網站太多,還是去GitHub - soimort/you-get: Dumb downloader that scrapes the web看吧,如果你有其他網站的需求,歡迎去PR添加支持,未來讓其他同學也能受益。


還不快去用!!!


you-get的可擴展爬蟲實現非常值得學習,相信給它貢獻代碼甚至讀了它的源碼都會對你的爬蟲技術有所提高的。


第二條: 不要只看 Web 網站, 還有移動版、 App 和 H5, 它們的反爬蟲措施一般比較少, 所有社交網站爬蟲, 優先選擇爬移動版。 這條大家好像都是直接忽略的... 憂傷

歡迎關注本人的微信公眾號獲取更多Python相關的內容(也可以直接搜索「Python之美」):

http://weixin.qq.com/r/D0zH35LE_s_Frda89xkd (二維碼自動識別)


這幾天寫了一個爬蟲,這是我關於反爬蟲的一些總結: 常見的反爬蟲和應對方法 - Python Hacker - 知乎專欄

剛開始寫爬蟲用的是urllib2,後來知道了requests,驚為天人。
剛開始解析網頁用的是re,後來知道了BeautifulSoup,解析頁面不能再輕鬆。
再後來看別人的爬蟲,知道了scrapy,被這個框架驚艷到了。
之後遇到了一些有驗證碼的網站,於是知道了PIL。但後來知道了opencv,pybrain。當在爬蟲中用上人工神經網路識別出驗證碼,興奮得守在爬蟲旁邊看他爬完全站。
再後來知道了threading,知道了celery。

不斷的學習,不斷的接觸和知道更多的東西,爬蟲與反爬蟲的對抗會一直進行下去。


以前啊,抓論壇帖子,爬蟲跑了一會兒ip就被封了.
然後我就把user-agent改 Baiduspider+
就一直沒出現過問題.


說一個我的,不算瞠目結舌。我當時爬一個網站的時候需要大量代理,正好手上有不少PHP的虛擬空間,就是萬網賣的那種,幾十塊錢一年,只能上傳PHP代碼。我就用PHP寫了一個代理腳本,應該算應用層代理了吧,還加了雙向介面驗證,偽裝成普通文件,瞬間有了幾十個代理,一直在用,這個代理好像也不可追蹤。
===========================================================
其實非常簡單,把url用GET 或者POST提交給PHP腳本,腳本用file_put_contents(url)獲取數據,然後把數據返回給你就行了。完全匿名哈哈。


人肉爬蟲


額,說個囧事吧。最近在學go,隨手用go寫了個小爬蟲,從入口頁開始解析並找到站內地址,然後開個goroutine去爬,對,沒有控制線程數。用的公司的代理出口,然後順手用hduoj做測試,結果瞬間把它爬掛了…我真的只是測試一下代碼而已,不是故意DOS你們的啊…


說一個只有在大規模爬取的時候才用得到的技巧吧.
比如你在建立一個汽車資料庫, 需要從 上百萬各種來源爬一大堆元數據, 肯定不能靠人了, 訓練一個模型也太花時間.

有一種簡單可行的辦法, 首先去google或者垂直網站抓元數據
想辦法將元數據與它來源的url配對 (比如google肯定會有來源url)
這樣對於一個url, 你能知道它的提取結果是什麼, 然後能找到對應頁面什麼位置
然後逆向出頁面模板

因為這些頁面都是模板生成的, 於是對整站套用模板, ok, 數據出來了.


Python新手一枚。

昨天跑爬蟲,防止被目標網站ban掉,設定的爬取延時較高,已經跑了十多個小時了還沒跑完,項目組長那邊又急著要數據,但是我的數據寫入函數是在爬蟲結束(close)的時候才會寫入,爬蟲結束之前都是放在緩存中的, 眼看著這十多個小時的數據就要沉沒了啊。 咋辦?

強行中斷程序,然後縮小爬取規模重開?

NO~NO~NO

直接拔了電腦網線,爬蟲抖了幾下發現連不上網了哎~ 自己乖乖兒close,把數據寫入文件了。


ps:用的scrapy框架 + selenium phantomjs


因為正在搞一套自用爬蟲框架所以冒個泡泡……

寫爬蟲什麼的……我想說純Python爬蟲寫起來並不爽啊……要爽必須是Python寫分散式調度+CasperJS/PhantomJS的神奇組合。


CasperJS已經把寫爬蟲從構造請求的層面拽到了模擬動作的層面,以至於以前要費勁抓非同步請求看js湊參數一系列流程變成了點擊、填表、點擊這樣的動作模擬,對於一臉的ajax頁面和所謂的SPA應用抓起來跟玩一樣……

啊當然這套辦法對搜索引擎式的通用爬蟲還是不太好使的,畢竟慢不少。


瞠目結舌啊?

有個爬蟲變著UA爬我的站。。。然而IP沒變。。。

於是就給封掉了。。。瞠目結舌啊!


最開始的時候…我用按鍵精靈當爬蟲 可以把一個特別整齊的表抓到Excel里…
效果…居然還不錯…


之前都是在本地找個開源框架寫爬蟲,現在發現可以在雲上寫爬蟲了,幾行代碼搞定直接上線跑。源碼地址:GitHub - ShenJianShou/crawler_samples: 各種爬取規則示例,可以直接在 神箭手雲爬蟲開發平台 上運行


我們公司是一個靠爬蟲盈利的公司。

除了上面這些常見技巧之外,還有一個很重要的事情,就是購買了真正的商業代理服務。專業的代理服務就是能讓你想用哪個國家的IP就用哪個,隨時切換,而且沒有後顧之憂。


# python框架tornado官方文檔爬蟲示例

import time
from datetime import timedelta

try:
from HTMLParser import HTMLParser
from urlparse import urljoin, urldefrag
except ImportError:
from html.parser import HTMLParser
from urllib.parse import urljoin, urldefrag

from tornado import httpclient, gen, ioloop, queues

base_url = "http://www.tornadoweb.org/en/stable/"
concurrency = 10

@gen.coroutine
def get_links_from_url(url):
"""Download the page at `url` and parse it for links.

Returned links have had the fragment after `#` removed, and have been made
absolute so, e.g. the URL "gen.html#tornado.gen.coroutine" becomes
"http://www.tornadoweb.org/en/stable/gen.html".
"""
try:
response = yield httpclient.AsyncHTTPClient().fetch(url)
print("fetched %s" % url)

html = response.body if isinstance(response.body, str)
else response.body.decode()
urls = [urljoin(url, remove_fragment(new_url))
for new_url in get_links(html)]
except Exception as e:
print("Exception: %s %s" % (e, url))
raise gen.Return([])

raise gen.Return(urls)

def remove_fragment(url):
pure_url, frag = urldefrag(url)
return pure_url

def get_links(html):
class URLSeeker(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.urls = []

def handle_starttag(self, tag, attrs):
href = dict(attrs).get("href")
if href and tag == "a":
self.urls.append(href)

url_seeker = URLSeeker()
url_seeker.feed(html)
return url_seeker.urls

@gen.coroutine
def main():
q = queues.Queue()
start = time.time()
fetching, fetched = set(), set()

@gen.coroutine
def fetch_url():
current_url = yield q.get()
try:
if current_url in fetching:
return

print("fetching %s" % current_url)
fetching.add(current_url)
urls = yield get_links_from_url(current_url)
fetched.add(current_url)

for new_url in urls:
# Only follow links beneath the base URL
if new_url.startswith(base_url):
yield q.put(new_url)

finally:
q.task_done()

@gen.coroutine
def worker():
while True:
yield fetch_url()

q.put(base_url)

# Start workers, then wait for the work queue to be empty.
for _ in range(concurrency):
worker()
yield q.join(timeout=timedelta(seconds=300))
assert fetching == fetched
print("Done in %d seconds, fetched %s URLs." % (
time.time() - start, len(fetched)))

if __name__ == "__main__":
import logging
logging.basicConfig()
io_loop = ioloop.IOLoop.current()
io_loop.run_sync(main)

來自tornado官方文檔Queue example,這個是tornado示例里一個高效的非同步爬蟲。可以用來爬一些萬級頁面數量的網站。稍微改下自己用: pip install tornado

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import time
from datetime import timedelta
from tornado import httpclient, gen, ioloop, queues
import traceback

class AsySpider(object):
"""A simple class of asynchronous spider."""
def __init__(self, urls, concurrency=10, results=None, **kwargs):
urls.reverse()
self.urls = urls
self.concurrency = concurrency
self._q = queues.Queue()
self._fetching = set()
self._fetched = set()
if results is None:
self.results = []

def fetch(self, url, **kwargs):
fetch = getattr(httpclient.AsyncHTTPClient(), "fetch")
return fetch(url, raise_error=False, **kwargs)

def handle_html(self, url, html):
"""handle html page"""
print(url)

def handle_response(self, url, response):
"""inherit and rewrite this method if necessary"""
if response.code == 200:
self.handle_html(url, response.body)

elif response.code == 599: # retry
self._fetching.remove(url)
self._q.put(url)

@gen.coroutine
def get_page(self, url):
try:
response = yield self.fetch(url)
#print("######fetched %s" % url)
except Exception as e:
print("Exception: %s %s" % (e, url))
raise gen.Return(e)
raise gen.Return(response)

@gen.coroutine
def _run(self):
@gen.coroutine
def fetch_url():
current_url = yield self._q.get()
try:
if current_url in self._fetching:
return

#print("fetching****** %s" % current_url)
self._fetching.add(current_url)

response = yield self.get_page(current_url)
self.handle_response(current_url, response) # handle reponse

self._fetched.add(current_url)

for i in range(self.concurrency):
if self.urls:
yield self._q.put(self.urls.pop())

finally:
self._q.task_done()

@gen.coroutine
def worker():
while True:
yield fetch_url()

self._q.put(self.urls.pop()) # add first url

# Start workers, then wait for the work queue to be empty.
for _ in range(self.concurrency):
worker()

yield self._q.join(timeout=timedelta(seconds=300000))
try:
assert self._fetching == self._fetched
except AssertionError:
print(self._fetching-self._fetched)
print(self._fetched-self._fetching)

def run(self):
io_loop = ioloop.IOLoop.current()
io_loop.run_sync(self._run)

class MySpider(AsySpider):

def fetch(self, url, **kwargs):
"""重寫父類fetch方法可以添加cookies,headers,timeout等信息"""
cookies_str = "PHPSESSID=j1tt66a829idnms56ppb70jri4; pspt=%7B%22id%22%3A%2233153%22%2C%22pswd%22%3A%228835d2c1351d221b4ab016fbf9e8253f%22%2C%22_code%22%3A%22f779dcd011f4e2581c716d1e1b945861%22%7D; key=%E9%87%8D%E5%BA%86%E5%95%84%E6%9C%A8%E9%B8%9F%E7%BD%91%E7%BB%9C%E7%A7%91%E6%8A%80%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8; think_language=zh-cn; SERVERID=a66d7d08fa1c8b2e37dbdc6ffff82d9e|1444973193|1444967835; CNZZDATA1254842228=1433864393-1442810831-%7C1444972138"
headers = {
"User-Agent": "mozilla/5.0 (compatible; baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
"cookie": cookies_str
}
return super(MySpider, self).fetch(
url, headers=headers
)

def handle_html(self, url, html):
#print(url, html)
print(url)

def main():
urls = []
for page in range(1, 10000):
urls.append("http://www.baidu.com/?page=%s" % page)
s = MySpider(urls)
s.run()

if __name__ == "__main__":
main()

網速好的話,一萬個頁面應該是在2到4分鐘之內,充分利用了非同步優勢。不過代碼真不好看。


用1024練手……不怕沒有動力……


為什麼關注點都在怎麼爬?我認為應該在URL相似性啊,掃描器必備啊


歪個樓。

我想跟大家分享一下令人瞠目結舌的反爬蟲技巧

一個師兄委託我去抓專利數據,這個神奇的網站叫做「中國專利資料庫」,就是知網那個:

經過一些體力勞動,代碼跑起來了,但是出現了一個非常詭異的問題,就是每次爬到第7頁就卡在那裡不動了,我甚至有一次賭氣把sleep時間設置成了5秒。依然,未果,尋病終。

百思不得其解。

後來我絕望地用手一頁一頁地點「下一頁」,然後終於發現了問題之所在:

原來無論怎麼樣最多只能看到350條記錄。。。之前之所以卡在第七頁是因為我一個request參數設置了每頁50條記錄。改成每頁10條記錄之後,果然卡在了第35頁。。。

所以這裡的反爬蟲技巧就是連人類都不給你看。

不過,這倒是很有道理:

「建議你重新組合檢索條件,檢索內容更準確」

估計知網的內心OS是:好心給你查專利,你竟然想爬我!


聽說的,不是親眼見過。

有工科男通過爬蟲技術獲取女神1000多條人人狀態,然後分析出女神愛吃什麼,好朋友是誰,作息時間,還有生理周期。

但依舊然並卵……


曾經為了爬淘寶商品數據,使用了幾十個Goagent帳號做代理逃避淘寶的反爬蟲


蚯蚓斷成兩截還能活!!!


推薦閱讀:

計算化學領域中有哪些技術可以被稱為是當前的黑科技?

TAG:程序員 | Python | 計算機 | 爬蟲 (計算機網路) | 黑科技 |