學習爬蟲有一段時間了资厉,今天想在此寫一篇基于新手對爬蟲入門的理解和初級爬蟲的構(gòu)建的文章厅缺。說白了,這篇文章,是寫給比我還菜的人看的湘捎。別看了诀豁,說的就是你。
一個簡單的爬蟲構(gòu)建我們采取一個簡單的思路:
抓取網(wǎng)頁
本次我們要抓取的頁面是全唐詩窥妇,它的首頁長這樣:
依次點進去查看前幾個頁面的url舷胜,我們就會發(fā)現(xiàn)這些頁面之間的規(guī)律:
好了,經(jīng)過簡單的觀察活翩,我們發(fā)現(xiàn)這些頁面的url有一個字段是從0001增長到了0900烹骨,一共九百頁,而其他地方則沒有變化纱新,這就好辦了展氓!但是也不要認為這個爬蟲就這么簡單,這些頁面要抓取就是一整頁脸爱,如何把這一整頁詩詞抽離出每首詩并寫入數(shù)據(jù)庫呢遇汞?接下來開始寫爬蟲
def gethtml(self,url):
try :
response = requests.get(url, headers=self.headers)
response.encoding = 'gb18030'
except :
pass
else :
html = lxml.html.fromstring(response.text)
finally:
return html
這個方法是專門用來抓取網(wǎng)頁源代碼的,它接受一個網(wǎng)頁URL作為參數(shù)簿废,將網(wǎng)頁源碼轉(zhuǎn)換為html元素并返回空入,并且隨時準備被再次調(diào)用,至于response的編碼族檬,這里采取了gb18030歪赢,因為古詩詞里面的生僻字太多了,另外再說一句单料,爬蟲新手最頭疼的問題編碼可能算一個埋凯,采用requests庫的時候,我們一般調(diào)用網(wǎng)頁自身的編碼方式來給網(wǎng)頁的響應(yīng)流編碼:
response.encoding = response.apparent_encoding
但本教程是個例外扫尖,因為古詩詞里面的生僻字實在是太多了~~~
抽取元素
抽取元素我們使用xpath白对,高效又簡潔,正則表達式和beautifulsoup我都嘗試過换怖,但始終不如xpath深入我心甩恼。
檢查網(wǎng)頁源代碼,我們只要獲取DIV標簽下面的文本就好了
page = html.xpath('.//div/text()')
數(shù)據(jù)處理
上面我說過沉颂,這一頁詩拿下來我們需要對其做數(shù)據(jù)抽取条摸,這個時候不著急寫代碼,應(yīng)該停下來認真觀察拿到的詩文铸屉,選擇一個最好的規(guī)則應(yīng)用到其中钉蒲,做到最優(yōu)化的從詩文集合里分離單首詩文。這里我們注意到彻坛,每首詩的標題以「」包圍的子巾,我們的規(guī)則是上一個包含「」的行到下一個包含「」的行之間的內(nèi)容為一首詩帆赢,然后再把「」里的詩名跟后面的作者都抽離出來,最終寫入數(shù)據(jù)庫线梗,代碼如下:
import csv
import pymysql
conn = pymysql.connect(host='localhost',port=3306,user='root',password='xxxx',db='xxx',charset='utf8')
cur = conn.cursor()
with open('tangshi.txt','r+',encoding='utf8') as f:
with open('tangshi.csv','w+',encoding='utf8') as csvfile:
writer = csv.writer(csvfile)
items = f.readlines()
lst = []
for index, item in enumerate(items):
if '」' in item:
lst.append(index) #存放了所有標題的索引
for index, item in enumerate(lst): #以索引-值 的形式遍歷列表
lst2 = items[item].split('「')
author = lst2[-1].split('」')[-1]
title = lst2[-1].split('」')[-2]
if items[lst[index]] != items[lst[-1]]: #如果這個標題不是最后一個
context = items[lst[index]+1:lst[index+1]]
context = ''.join([i.strip() for i in content if i ]) #做列表轉(zhuǎn)字符串的處理
else:
context = items[lst[index]+1:] #否則詩文是該標題到此文本的末尾
context = ''.join([i.strip() for i in context if i])
sql = 'insert into tangshi(title,author,context) values(%s,%s,%s)'
cur.execute(sql, (title.strip(),author.strip(),context.strip()))
conn.commit()
cur.close()
conn.close()
說到最后,我把爬蟲的源代碼貼在這里怠益,python環(huán)境3.5仪搔,應(yīng)該可以直接運行。時間倉促加上語言不夠精煉蜻牢,可能有些地方說的不夠明白烤咧,請大家見諒,也歡迎讀者提出疑問或者獻上你寶貴的意見抢呆。下回見煮嫌!
import requests
import lxml.html
class myspider():
#定義內(nèi)置方法,跟隨類一起創(chuàng)建抱虐,全局變量一般在此方法下聲明
def __init__(self):
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36'
self.headers = {'User-Agent':user_agent}
#定義獲取相應(yīng)url的html
def gethtml(self,url):
try :
response = requests.get(url, headers=self.headers)
response.encoding = 'gb18030'
except :
pass
else :
html = lxml.html.fromstring(response.text)
finally:
return html
def getpage(self,url,num):
with open('D:/{0}.txt'.format(num[1]),'w',encoding='utf8') as f :
for i in range(1,num[0]):
print('正寫入第{0}頁'.format(i))
s = str(i).zfill(4)
print(s)
ur = url.format(s)
html = self.gethtml(ur)
print(ur)
page = html.xpath('.//div/text()')
for j in page :
if j :
j.strip('\n')
f.write(j)
print('寫入完畢')
if __name__=='__main__':
sp = myspider()
url1 = 'http://www.shigeku.org/shiku/gs/tangshi/qts_{0}.htm'
d ={url1:[901,'tangshi']}
for url,num in d.items():
sp.getpage(url,num)