Python並不是我的主業,當初學Python主要是爲了學爬蟲,以爲自己覺得能夠從網上爬東西是一件非常神奇又是一件非常有用的事情,因爲我們可以獲取一些方面的數據或者其他的東西,反正各有用處。
這兩天閒着沒事,主要是讓腦子放鬆一下就寫着爬蟲來玩,上一篇初略的使用BeautifulSoup去爬某個CSDN博客的基本統計信息(http://blog.csdn.net/hw140701/article/details/55048364),今天就想要不就直接根據某個CSDN博客的主頁的地址爬取該博客的所有文章鏈接,進而提取每一篇文章中的元素,我這裏是提取每一篇博客
一、主要思路
通過分析CSDN博客的網站源碼,我們發現當我們輸入某博客主頁網址時,如:http://blog.csdn.net/hw140701
在主頁會有多篇文章,以及文章的鏈接,默認的是15篇。在主頁博客的底部會有分頁的鏈接,如下圖
如圖所示,一共65篇分5頁,每一頁中又包含了15篇文章的鏈接。
所以我們總體的思路是:
1.輸入博客主頁地址,先獲取當前頁所有文章的鏈接;
2.獲取每個分頁的鏈接地址
3.通過每個分頁的鏈接地址獲取每一個分頁上所有文章的鏈接地址
4.根據每一篇文章的鏈接地址,獲取每一篇文章的內容,直到該博客所有文章都爬取完畢
二、代碼分析
2.1分頁鏈接源碼分析
用瀏覽器打開網頁地址,使用開發者工具查看博客主頁網站源碼,發現分頁鏈接地址隱藏在下列標籤之中
所以我們通過下列代碼所有分頁鏈接進行匹配
[python] view plain copy
- bsObj.findAll("a",href=re.compile("^/([A-Za-z0-9]+)(/article)(/list)(/[0-9]+)*$")):#正則表達式匹配分頁的鏈接
bsObj爲BeautifulSoup對象
2.2分頁上每一篇文章鏈接源碼分析
得到每一個分頁的鏈接後,對每一個分頁上的文章鏈接源碼進行分析,其源碼如下
通過分析,所以我們採取以下的方法進行匹配
[python] view plain copy
- bsObj.findAll("a",href=re.compile("^/([A-Za-z0-9]+)(/article)(/details)(/[0-9]+)*$"))
或者
[python] view plain copy
- bsObj.findAll("span",{"class":"link_title"})
2.3每一篇文章中文字內容源碼分析
通過對每一篇文章中的網站源碼進行分析,發現其內容位於源碼中的以下位置
所以通過下列代碼進行匹配
[python] view plain copy
- bsObj.findAll("span",style=re.compile("font-size:([0-9]+)px"))
3.全部代碼以及結果
現附上全部代碼,註釋部分可能有錯,可以根據此代碼自行修改,去爬取某CSDN博客中的任意元素
[python] view plain copy
- #__author__ = 'Administrat
- #coding=utf-8
- import io
- import os
- import sys
- import urllib
- from urllib.request import urlopen
- from urllib import request
- from bs4 import BeautifulSoup
- import datetime
- import random
- import re
- import requests
- import socket
- socket.setdefaulttimeout(5000)#設置全局超時函數
- sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')
- headers1={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}
- headers2={'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'}
- headers3={'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}
- #得到CSDN博客某一個分頁的所有文章的鏈接
- articles=set()
- def getArticleLinks(pageUrl):
- #設置代理IP
- #代理IP可以上http://zhimaruanjian.com/獲取
- proxy_handler=urllib.request.ProxyHandler({'post':'210.136.17.78:8080'})
- proxy_auth_handler=urllib.request.ProxyBasicAuthHandler()
- opener = urllib.request.build_opener(urllib.request.HTTPHandler, proxy_handler)
- urllib.request.install_opener(opener)
- #獲取網頁信息
- req=request.Request(pageUrl,headers=headers1 or headers2 or headers3)
- html=urlopen(req)
- bsObj=BeautifulSoup(html.read(),"html.parser")
- global articles
- #return bsObj.findAll("a",href=re.compile("^/([A-Za-z0-9]+)(/article)(/details)(/[0-9]+)*$"))
- #return bsObj.findAll("a")
- #for articlelist in bsObj.findAll("span",{"class":"link_title"}):
- for articlelist in bsObj.findAll("span",{"class":"link_title"}):#正則表達式匹配每一篇文章鏈接
- #print(articlelist)
- if 'href' in articlelist.a.attrs:
- if articlelist.a.attrs["href"] not in articles:
- #遇到了新界面
- newArticle=articlelist.a.attrs["href"]
- #print(newArticle)
- articles.add(newArticle)
- #articlelinks=getArticleLinks("http://blog.csdn.net/hw140701")
- #for list in articlelinks:
- #print(list.attrs["href"])
- #print(list.a.attrs["href"])
- #寫入文本
- #def data_out(data):
- # with open("E:/CSDN.txt","a+") as out:
- # out.write('\n')
- # out.write(data,)
- #得到CSDN博客每一篇文章的文字內容
- def getArticleText(articleUrl):
- #設置代理IP
- #代理IP可以上http://zhimaruanjian.com/獲取
- proxy_handler=urllib.request.ProxyHandler({'https':'111.76.129.200:808'})
- proxy_auth_handler=urllib.request.ProxyBasicAuthHandler()
- opener = urllib.request.build_opener(urllib.request.HTTPHandler, proxy_handler)
- urllib.request.install_opener(opener)
- #獲取網頁信息
- req=request.Request(articleUrl,headers=headers1 or headers2 or headers3)
- html=urlopen(req)
- bsObj=BeautifulSoup(html.read(),"html.parser")
- #獲取文章的文字內容
- for textlist in bsObj.findAll("span",style=re.compile("font-size:([0-9]+)px")):#正則表達式匹配文字內容標籤
- print(textlist.get_text())
- #data_out(textlist.get_text())
- #得到CSDN博客某個博客主頁上所有分頁的鏈接,根據分頁鏈接得到每一篇文章的鏈接並爬取博客每篇文章的文字
- pages=set()
- def getPageLinks(bokezhuye):
- #設置代理IP
- #代理IP可以上http://zhimaruanjian.com/獲取
- proxy_handler=urllib.request.ProxyHandler({'post':'121.22.252.85:8000'})
- proxy_auth_handler=urllib.request.ProxyBasicAuthHandler()
- opener = urllib.request.build_opener(urllib.request.HTTPHandler, proxy_handler)
- urllib.request.install_opener(opener)
- #獲取網頁信息
- req=request.Request(bokezhuye,headers=headers1 or headers2 or headers3)
- html=urlopen(req)
- bsObj=BeautifulSoup(html.read(),"html.parser")
- #獲取當前頁面(第一頁)的所有文章的鏈接
- getArticleLinks(bokezhuye)
- #去除重複的鏈接
- global pages
- for pagelist in bsObj.findAll("a",href=re.compile("^/([A-Za-z0-9]+)(/article)(/list)(/[0-9]+)*$")):#正則表達式匹配分頁的鏈接
- if 'href' in pagelist.attrs:
- if pagelist.attrs["href"] not in pages:
- #遇到了新的界面
- newPage=pagelist.attrs["href"]
- #print(newPage)
- pages.add(newPage)
- #獲取接下來的每一個頁面上的每一篇文章的鏈接
- newPageLink="http://blog.csdn.net/"+newPage
- getArticleLinks(newPageLink)
- #爬取每一篇文章的文字內容
- for articlelist in articles:
- newarticlelist="http://blog.csdn.net/"+articlelist
- print(newarticlelist)
- getArticleText(newarticlelist)
- #getArticleLinks("http://blog.csdn.net/hw140701")
- getPageLinks("http://blog.csdn.net/hw140701")
- #getArticleText("http://blog.csdn.net/hw140701/article/details/55104018")
結果
在其中有時候會出現亂碼,這是由於有空格的存在,暫時還有找到方法解決。
另外在有的時候會出現服務器沒有響應的錯誤,如下: