您好,登錄后才能下訂單哦!
源碼網址: http://download.csdn.NET/detail/hanchaobiao/9860671
一段自動抓取互聯網信息的程序,可以從一個URL出發,訪問它所關聯的URL,提取我們所需要的數據。也就是說爬蟲是自動訪問互聯網并提取數據的程序。
爬蟲調度端:用來啟動、執行、停止爬蟲,或者監視爬蟲中的運行情況
在爬蟲程序中有三個模塊URL管理器:對將要爬取的URL和已經爬取過的URL這兩個數據的管理
網頁下載器:將URL管理器里提供的一個URL對應的網頁下載下來,存儲為一個字符串,這個字符串會傳送給網頁解析器進行解析
網頁解析器:一方面會解析出有價值的數據,另一方面,由于每一個頁面都有很多指向其它頁面的網頁,這些URL被解析出來之后,可以補充進URL管理 器
這三部門就組成了一個簡單的爬蟲架構,這個架構就能將互聯網中所有的網頁抓取下來
防止重復抓取和循環抓取,最嚴重情況兩個URL相互指向就會形成死循環
三種實現方式
Python內存set集合:set集合支持去重的作用
MySQL:url(訪問路徑)is_crawled(是否訪問)
Redis:使用redis性能最好,且Redis中也有set類型,可以去重。不懂得同學可以看下Redis的介紹
四、網頁下載器和urlib模塊
本文使用urllib實現
urllib2是python自帶的模塊,不需要下載。
urllib2在python3.x中被改為urllib.request
三種實現方式
方法一:
[python] view plain copy
#引入模塊
from urllib import request
url = "http://www.baidu.com"
#第一種下載網頁的方法
print("第一種方法:")
#request = urllib.urlopen(url) 2.x
response1 = request.urlopen(url)
print("狀態碼:",response1.getcode())
#獲取網頁內容
html = response1.read()
#設置編碼格式
print(html.decode("utf8"))
#關閉response1
response1.close()
方法二:
[python] view plain copy
print("第二種:")
request2 = request.Request(url)
request2.add_header('user-agent','Mozilla/5.0')
response2 = request.urlopen(request2)
print("狀態碼:",response2.getcode())
#獲取網頁內容
htm2 = response2.read()
#調整格式
print(htm2.decode("utf8"))
#關閉response1
response2.close()
方法三:使用cookie
[html] view plain copy
<span style="font-size:12px;">#第三種方法 使用cookie獲取
import http.cookiejar
cookie = http.cookiejar.LWPCookieJar()
opener = request.build_opener(request.HTTPCookieProcessor(cookie))
request.install_opener(opener)
response3 = request.urlopen(url)
print(cookie)
html3 = response3.read()
#將內容格式排列
print(html3.decode("utf8"))
response3.close()</span>
測試是否安裝bs4
[python] view plain copy
import bs4
print(bs4)
打印結果:<module 'bs4' from 'D:\\app\\Python\\Anaconda\\lib\\site-packages\\bs4\\__init__.py'>
則安裝成功
Beautiful Soup 相比其他的html解析有個非常重要的優勢。html會被拆解為對象處理。全篇轉化為字典和數組。
相比正則解析的爬蟲,省略了學習正則的高成本,本文使用python3.x系統自帶不需要安裝。
使用案例:http://blog.csdn.net/watsy/article/details/14161201
方法介紹
html采用官方案例
[python] view plain copy
#引用模塊
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a >Elsie</a>,
<a >Lacie</a> and
<a >Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
獲取所有的鏈接
[python] view plain copy
print("獲取所有的鏈接")
links = soup.find_all('a') #a標簽
for link in links:
print(link.name,link['href'],link.get_text())
[python] view plain copy
#獲取href=http://example.com/lacie的鏈接
print("獲取lacie鏈接")
link1 = soup.find('a',href="http://example.com/lacie")
print(link1.name,link1['href'],link1.get_text())
[python] view plain copy
print("正則匹配 href中帶有“ill”的")
import re #導入re包
link2 = soup.find('a',href=re.compile(r"ill"))
print(link2.name,link2['href'],link2.get_text())
[python] view plain copy
print("獲取p段落文字")
link3 = soup.find('p',class_="title") #class是關鍵字 需要加_
print(link3.name,link3.get_text())
入口:http://baike.baidu.com/item/Python
分析URL格式:防止訪問無用路徑 http://baike.baidu.com/item/{標題}
數據:抓取百度百科相關Python詞條網頁的標題和簡介
通過審查元素得標題元素為 :class="lemmaWgt-lemmaTitle-title"
簡介元素為:class="lemma-summary"
頁面編碼:UTF-8
作為定向爬蟲網站要根據爬蟲的內容升級而升級如運行出錯可能為百度百科升級,此時則需要重新分析目標
代碼集注釋:
[python] view plain copy
#創建類
from imooc.baike_spider import url_manager,html_downloader,html_output,html_parser
class spiderMain:
#構造函數 初始化
def __init__(self):
#實例化需引用的對象
self.urls = url_manager.UrlManager()
self.downloader = html_downloader.HtmlDownLoader()
self.output = html_output.HtmlOutPut()
self.parser = html_parser.HtmlParser()
def craw(self,root_url):
#添加一個到url中
self.urls.add_new_url(root_url)
count = 1
while self.urls.has_new_url():
try:
new_url = self.urls.get_new_url()
print('craw %d : %s' %(count,new_url))
#下載
html_context = self.downloader.downloade(new_url)
new_urls,new_data = self.parser.parse(new_url,html_context)
print(new_urls)
self.urls.add_new_urls(new_urls)
self.output.collect_data(new_data)
#爬一千個界面
if(count==1000):
break
count+=1
except:
print("craw faile")
self.output.output_html()
#創建main方法
if __name__ == "__main__":
root_url = "http://baike.baidu.com/item/Python"
obj_spider = spiderMain()
obj_spider.craw(root_url)
[python] view plain copy
class UrlManager:
'url管理類'
#構造函數初始化set集合
def __init__(self):
self.new_urls = set() #待爬取的url
self.old_urls = set() #已爬取的url
#向管理器中添加一個新的url
def add_new_url(self,root_url):
if(root_url is None):
return
if(root_url not in self.new_urls and root_url not in self.old_urls):
#既不在待爬取的url也不在已爬取的url中,是一個全新的url,因此將其添加到new_urls
self.new_urls.add(root_url)
# 向管理器中添加批量新的url
def add_new_urls(self,urls):
if(urls is None or len(urls) == 0):
return
for url in urls:
self.add_new_url(url) #調用add_new_url()
#判斷是否有新的待爬取的url
def has_new_url(self):
return len(self.new_urls) != 0
#獲取一個待爬取的url
def get_new_url(self):
new_url = self.new_urls.pop()
self.old_urls.add(new_url)
return new_url
[python] view plain copy <span >from urllib import request from urllib.parse import quote import string class HtmlDownLoader: '下載頁面內容' def downloade(self,new_url): if(new_url is None): return None #解決請求路徑中含義中文或特殊字符 url_ = quote(new_url, safe=string.printable); response = request.urlopen(url_) if(response.getcode()!=200): return None #請求失敗 html = response.read() return html.decode("utf8")</span>
[python] view plain copy
from bs4 import BeautifulSoup
import re
from urllib import parse
class HtmlParser:
#page_url 基本url 需拼接部分
def _get_new_urls(self,page_url,soup):
new_urls = set()
#匹配 /item/%E8%87%AA%E7%94%B1%E8%BD%AF%E4%BB%B6
links = soup.find_all('a',href=re.compile(r'/item/\w+'))
for link in links:
new_url = link["href"]
#例如page_url=http://baike.baidu.com/item/Python new_url=/item/史記·2016?fr=navbar
#則使用parse.urljoin(page_url,new_url)后 new_full_url = http://baike.baidu.com/item/史記·2016?fr=navbar
new_full_url = parse.urljoin(page_url,new_url)
new_urls.add(new_full_url)
return new_urls
def _get_new_data(self,page_url,soup):
#<dd class="lemmaWgt-lemmaTitle-title"> <h2>Python</h2>
red_data = {}
red_data['url'] = page_url
title_node = soup.find('dd',class_="lemmaWgt-lemmaTitle-title").find('h2') #獲取標題內容
red_data['title'] = title_node.get_text()
#<div class="lemma-summary" label-module="lemmaSummary">
summary_node = soup.find('div',class_="lemma-summary")
red_data['summary'] = summary_node.get_text()
return red_data
#new_url路徑 html_context界面內容
def parse(self,page_url, html_context):
if(page_url is None or html_context is None):
return
#python3缺省的編碼是unicode, 再在from_encoding設置為utf8, 會被忽視掉,去掉【from_encoding = "utf-8"】這一個好了
soup = BeautifulSoup(html_context, "html.parser")
new_urls = self._get_new_urls(page_url, soup)
new_data = self._get_new_data(page_url, soup)
return new_urls,new_data
[python] view plain copy
class HtmlOutPut:
def __init__(self):
self.datas = [] #存放搜集的數據
def collect_data(self,new_data):
if(new_data is None):
return
self.datas.append(new_data)
def output_html(self):
fout = open('output.html','w',encoding='utf8') #寫入文件 防止中文亂碼
fout.write('<html>\n')
fout.write('<body>\n')
fout.write('<table>\n')
for data in self.datas:
fout.write('<tr>\n')
fout.write('<td>%s</td>\n'%data['url'])
fout.write('<td>%s</td>\n'%data['title'])
fout.write('<td>%s</td>\n'%data['summary'])
fout.write('</tr>\n')
fout.write('</table>\n')
fout.write('</body>\n')
fout.write('</html>\n')
fout.close()
視頻網站:http://www.imooc.com/learn/563
源碼網址:http://download.csdn.Net/detail/hanchaobiao/9860671
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。