爬蟲學習筆記
list
extend函數 將兩個list連起來
整齊打印抓到的html頁面:直接print re.text就行
str 替換函數,replace,替換字符串內容
list index()求 元素的下標
字符串中加數字: sd=’%s_%s’%(i,t)
. for (i1, i2) in zip(list1,list2): 同時遍歷兩個list.找class span中的內容 self.title.append(lable.split(“\”“)[1])
str.isalpha()判斷是否是字母
str.isdigit()判斷是否是數字 判斷是否包含字母或者數字:re.search(‘[a-z]’,str)
jieba分詞:
txt = open("bxj.txt", "r", encoding='utf-8').read() words = jieba.lcut(txt) # words全部截取 counts = {} for word in words: if len(word) == 1: continue else: counts[word] = counts.get(word, 0) + 1 sd=sorted(counts.items(),key=lambda asd:asd[1],reverse=True)
tuple 強制轉換轉list
sd=list(sd)
解析數據
Beautifulsoup
初始化
soup = BeautifulSoup(html, ‘html.parser’)
深層次查找標籤
bs4可以通過find 或者find_all()返回後再次調用,find或者find_all()
然後,通過result[‘href’]得到href的標籤
tag
有兩個屬性: name,attrs
找出所有鏈接
names=soup.find_all(‘a’,{‘class’:’headpic’})
for each in names:
# print(each)
href=each[‘href’]
print(href)bs4 find_all(‘td’)找出所有,其他也一樣
找出 sd=message.find_all(‘td’,{“class”:”tWhite”})
提取信息 只有一條的情況下: sd[0].getText
a=each.find(‘a’) print(a.text)得到a 中間text的文件內容
a=each.find(‘a’) print(a[href])找到a標籤中的href
tr=soup.find(attrs{‘id’:’places_area_row’}) 找出id 屬性值爲‘’ 的數據
bs 對象分爲4大類 Tag NavigableString BeautifulSoup Comment
tag:有兩個屬性: attrs name name 打印出來 標籤的類別 比如 span
tag.attrs: {‘class’: [‘f666’]}找出span中的屬性
tag.text打印出標籤內部的內容找到< li >中的文字,用.string方法
lxml
導入方式
import lxml.html//
tree=lxml.html.fromstring(html)
. td=tree.cssselect(‘tr# places_area__row > td.w2p_fw’)[0]
代表id,首先找到tr爲places_area的元素,然後找到td類屬性爲w2p_fw的元素然後text_content得到內容
選擇a內span 標籤 : a span
title 屬性爲 home 的所有標籤 a[title=home]
- 選擇class=link 的所有f a.link
獲得div標籤下的所有class
div_class=tree.xpath(‘//div/@class’)
print(div_class)
xpath學習
page = etree.HTML(html.lower().decode(‘utf-8’))
定位html標籤,相對路徑,絕對路徑
- 絕對
path.xpath(u”/html/body/p”) - 相對
path.xpath(“//p”) 找出所有的p標籤
定位到“
World News only on this page
p = page.xpath(u”/html/body/p[@style=’font-size: 200%’]”)
用如@name, @id, @value, @href, @src, @class….
函數text 取出p中的文本
position 是節點的位置 li[position()=2]”表示取得第二個li節點
代表所有的節點,比如用”/html/body//span可以取出body下第二級的所有span,而不管它上一級是div還是p或是其它什麼東東。
href 找出所有的a標籤和內容
hrefs=page.xpath(u”//a”)
for href in hrefs:
print(href.attrib)
print(href.text)’
找出鏈接
print(href.get(‘href’))
position
hrefs=page.xpath(u”//a[position()=2]”)
找出所有href標籤中的第二個
取不到的內容
用tail 屬性
print (u.tail)
結束節點後面的內容
解析字符串
處理url
- urljoin from urlparse import url
urls.append(urljoin(“https://tieba.baidu.com/“,each.get(‘href’)))
返回response的url: response.geturl()
- str 的操作:info=”.join(info.split()) 去掉所有的空格和換行符
不換行輸出 print(‘123123’, end=”)
plt.rcParams[‘font.sans-serif’] = [‘SimHei’] 解決中文亂
碼問題- dic.get(‘fan’)==None dic[‘fan’]=1 dic檢查元素是否存在 以及添加元素的方法
解析json
json.loads()
- 將json結構的str 轉換爲 python類型數據結構 dict類型
json.dumps()
- 將python 的數據結構 dict 轉換爲json結構的str
抓取知乎內容
抓取我的收藏:
li class=” “> a class=” “> 2
urlib 和urllib2學習
標準款
response=urllib2.open(‘http://python.org/‘)
html=response.read()
加上header 和數據
user_agent='Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Mobile Safari/537.36'
headers={'User-Agent':user_agent}
values={‘name’ : ‘Michael Foord’, ‘location’ : ‘Northampton’, ‘language’ : ‘Python’ }
headers={‘user_agent’:user_agent)
data=urllib.urlencode(values)
req=urllib2.request(‘http://python.org‘,data,headers)
response=urllib2.urlopen(req,)
html=response.read()
加上代理
proxy_handler=urllib2.ProxyHandler({“http”:”http://114.215.95.188:3128“})
opener=urllib2.build_opener(proxy_handler)
urllib2.install_opener(opener)
加上cookie
- 設置cookie cookie=cookielib.CookieJar()
- build一個opener opener=urlliib2.build_opener(urllib.HTTPCookieProcessor(cj))
- 使用opener打開構建的request請求
內容保存到本地
將html 寫入txt
html=req.text
with open('zhihu_html.text','w') as opener:
opener.write(html)
dest_dir爲本地地址
urllib.urlretrieve(url , dest_dir)
將url存在本地磁盤的方法
- 將抓取下來的網頁按照域名保存爲一個個文件夾,然後將域名後面的東西保存爲文件地址
解決亂碼
如果原始是GBK
html=unicode(html,’GBK’).encode(‘UTF-8’)
判斷遍歷的最大深度
最原始的網頁深度爲 1:
如果 抓取到的網頁來自原始網頁 被抓取的網頁深度+1
如果一個url的深度大於最大深度 就不把他加在隊列中
慢慢的 隊列就空了,抓取停止了
也就是說 設置最大深度爲4
最多再抓取三層的信息
項目總結 2018.4.19
算是第一個爬蟲小項目: 先總結一下
開始:通過crawler 方法,傳入基本信息
維護一個url隊列
從最初的url抓取到的url 如果抓取過,就 添加在對列中, deepth+=1如果url在本地磁盤緩存中,html就從本地緩存中調用
否則進行下載,並且將下載的頁面寫入緩存- 解析:通過正則解析html 找到需要的url
一個html頁面所有的url抓取完畢, 該html對應的url出隊列
- 解析:通過正則解析html 找到需要的url
定時,在下載時,爲了防止ip被封,寫一個定時類,可以在每次下載時延緩一定的時間
當隊列爲空,所有的抓取完畢時,調用回調函數,將信息寫在csv文件中(這是個缺點,如果網絡中斷,豈不是之前的信息都要gg)
在抓取完一個url後,將html 文件寫入本地緩存
文件功能:
playground.py:程序的入口
Downloader.py:下載方法的實現
disk_cache.py:頁面緩存的實現
待完善:
- 用芒果db來代替本地儲存
- 對爬蟲功能的增加,比如識破驗證碼,處理ajax請求
- csv文件那塊還要再商議一下
- 如果能用代理的話,也不錯
- 分佈式定時任務框架rabbitMq 和celery學一下
Mongo DB的使用
概念
集合:
mogod -dbpath 是儲存文檔的地方,相當於mysql的表格
集合沒有固定的結構,比較鬆散,但集合中的文檔,一般都有相關性
當插入一個文檔時,集合就會建立
document
爲主鍵 |
SQL術語/概念 | MongoDB術語/概念 | 解釋/說明 |
---|---|---|
database | database | 數據庫 |
table | collection | 數據庫表/集合 |
row | document | 數據記錄行/文檔 |
column | field | 數據字段/域 |
index | index | 索引 |
table joins | 表連接,MongoDB不支持 | |
primary key | primary key | 主鍵,MongoDB自動將_id字段設置 |
數據類型
ObjectId 類似唯一的主鍵
運行mongoDB
mongod
常用shell
show dbs
use db
dbname.system.* //查看數據庫的所有信息
insert
WriteResult({ “nInserted” : 1 })
刪除當前數據庫
db.dropDatabase()
創建集合
db.createCollection(“runoob”)
顯示所有集合
show collections
插入文檔
以下文檔可以存儲在 MongoDB 的 runoob 數據庫 的 col 集合中:
db.COLLECTION_NAME.insert(document)
db.col.insert({title: ‘MongoDB 教程’, description: ‘MongoDB 是一個 Nosql 數據庫’, by: ‘菜鳥教程’, url: ‘http://www.runoob.com‘, tags: [‘mongodb’, ‘database’, ‘NoSQL’], likes: 100 })
終端連接服務器進入shell :mongo
查看集合中的文檔
db.col.find()
db.collections.count() 查看錶中的元素個數
python連接mongodb 放在local中
- 默認端口號27017
2.終端輸入 mongo 進入sql命令行
mysql 爲key-value 模式
mongodb 的配置文件
/usr/local/etc
文件默認路徑:/usr/local/var/mongodb
修改了數據庫路徑
賦權: sudo chown id -u
/Users/fanjialiang2401/data/mongo/
查看mongodb 是否在運行
mongodb 正確退出方式:
mongo // 從linux命令行進入mongod命令行
use admin // 切換到管理員模式
db.shutdownServer() // 關閉mongodb服務
pymongo
shell
- show dbs
- use db
- db.webpage.find()找出collection爲webpage的所有元素
- db.webpage.count()
. db.webpage.find() - 搜索所有的值
for item in table.find():
print(item)
- db.collection.createIndex( { name: -1 } )
7.db.myColl.find( { category: “cafe” } ) - db.myColl.createIndex(
{ score: 1, price: 1, category: 1 },
{ collation: { locale: “fr” } } ) - db.myColl.find( { score: 5, category: “cafe” } )
高端方法
selenium
def get_html():
driver=webdriver.Firefox()
html=driver.get('https://search.jd.com/search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%89%8B%E6%9C%BA&gp=2&cid2=653&cid3=655&ev=exbrand_%E4%B8%89%E6%98%9F%28SAMSUNG%29%5E&page=1&s=1&click=0')
time.sleep(3)
driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")
time.sleep(3)
html = driver.find_element_by_xpath("//*").get_attribute("outerHTML")
return html
python shell
- client=MongoClient(‘localhost’,27017)
db = client.primer
db.webpage.find()找出collection爲webpage的所有元素
. tablename.remove({“name”: “mike”})- counts=table_name.count()
coll = db.dataset
刪除數據庫
client
查看錶中有多少元素
counts=table_name.count()
print(‘總行數:%s’%counts)找到一條記錄
cols=table_name.find_one()找特定的某一行
result=table_name.find({“name”:”fanjialiang”})
連接到對應的數據庫
連接數據庫名爲primer
db = client.primer
連接名稱爲dataset的collctions
coll = db.dataset
db=conn.get_database('local')
colletion=db.collection_names()
查找
result=db.webpage.find({‘url’:url})//查找出來的是遊標
- result=db.webpage.find_one({‘_id’:url})
result= ‘ads’
for i in result:
print(i)
將url設爲id
db.webpage.update({‘_id’:url},{‘$set’:{‘html’:html}},upsert=True)
刪除
tablename.remove({"name": "mike"})
- 插入
table_name.insert({“name”:’fanjialiang’,”age”:18})
ps aux | grep mongo 查看mongodb 然後kill掉
requests
請求格式
response=requests.get(url=self.begin_url,headers=self.headers,cookies=CookieJar)
下載文件:
url=http://flupy.org/data/flags/fr/fr.gif
iamge=request.get(url).content
open(‘a.gif,’wb’) as opener:
opener.write(image)
解析csv文件
file=open(‘csv/top-1m.csv.zip’,’r’)
with ZipFile(file) as zf:
csv_filename=zf.namelist()[0]
for _,website in csv.reader(zf.open(csv_filename)):
urls.append(‘http://’+website)
下載最受歡迎的網站
下載一千個網頁:
- 如果國內訪問不到,設置一個超時時間,返回url,添加在錯誤url list中
- 如果能訪問到,加在mongo數據庫中,並且爲加入的url,創建一個index序號,作爲主鍵
- 計算訪問花費的總時間。
- 設置數據庫名稱
- 回調函數先不創建
代理項目
- 不斷的從互聯網上抓取代理
- 將抓取下來的代理寫在csv中
- 將好的代理篩選出來,返回一個List
- 抓取其他網站時,採用從代理池中隨機選擇一個
百度貼吧項目
- 將title抓下來
將內容抓下來
然後打印title,和對應的內容
每打印一行,輸出換行
2.將頁數抓下來,維持一個隊列,每次從隊列中取url,如果沒訪問過加加在隊列中,否則跳過。
- 將抓下來的內容存放在mongoDB中 起名NBA50大
抓取淘寶模特信息
在主頁面把模特的href 抓下來,然後進入每個的個人頁面href
進入網頁後,抓取個人域名,在進入每個人的個人域名把照片抓取下來
在個人頁面上,把個人信息抓取下來,儲存爲csv文件
身高, 三圍 , 個人頁面, 等等
項目流程
downloader類負責下載 不要scrapeCallback方法了
hrottle類負責 限制速度
scrapeCallback爲回調類,在完成下載後調用回調類將消息寫入硬盤
diskCache 類負責將抓取的內容寫到硬盤中
Link_crawler爲總的開始