基于知識圖譜的古詩詞推薦-python+爬蟲+mysql+neo4j(一)
- 資料準備
這是個人最近大創專案的成果,整理一下發出來,第一次寫文
資料準備
https://www.xungushici.com/
這個網站內容還較為豐富,并且好像沒有反爬,新手黨的福音啊,我在最后爬取古詩的時候,連續訪問了幾萬次都沒有被封ip,簡直了,
一開始學爬蟲的時候,都是使用BeautifulSoup和re的組合,但是對文本爬取的效率極低(是我不會用),后來就用Xpath語法了,賊快,
import requests
from lxml import etree #匯入相應的包
url='https://www.xungushici.com/shici/1' #輸入我們的url
get = requests.get(url).text # get(url) 得到我們的網頁, text將源網頁轉化為字串
selector = etree.HTML(get) # 將原始碼轉換為xpath可以識別的TML格式
接下來就是找到要爬取的內容的xpath路徑
用瀏覽器(我的是chrome)打開網頁https://www.xungushici.com/shici/1,按一下F12進入查看原始碼,找到要爬取的內容在原始碼的位置,以標題為例,對著內容點擊右鍵,然后移到copy選項上,選擇copy xpath,相應內容的xpath就會復制了
#/html/body/div/div/div[1]/div[1]/div/h3 #這是最初復制出來的xpath
#//html/body/div/div/div[1]/div[1]/div/h3/text()#將它添頭加尾
selector.xpath('//html/body/div/div/div[1]/div[1]/div/h3/text()')#獲取標題的內容
運行之后發現出來的是串列

那就改一下
selector.xpath('//html/body/div/div/div[1]/div[1]/div/h3/text()')[0]
所以要耐心的實驗和細心的觀察
標題搞定,朝代和作者都是類似的,
但是正文又不一樣了

它的每一句詩詞都是分開的,也不能一個一個復制xpath,那會go die 的,觀察一下它的第一句的xpath
#/html/body/div/div/div[1]/div[1]/div/div[1]/text()[1]
那我們就可以猜出它的整首詩的xpath因該是
#/html/body/div/div/div[1]/div[1]/div/div[1]/text()
(如果熟悉xpath語法的話,當我沒說)
selector.xpath('//html/body/div/div/div[1]/div[1]/div/div[1]/text()')
添頭加尾就可以獲取正文了

發現是一個串列,那我們可以用join把它們給串起來
''.join(selector.xpath('//html/body/div/div/div[1]/div[1]/div/div[1]/text()'))

獲取內容的程序就差不多了,為了方便之后的寫代碼,我們可以采取字典的形式把各個xpath給組織起來
Xpath={'標題':'/html/body/div/div/div[1]/div[1]/div/h3',
'朝代':'/html/body/div/div/div[1]/div[1]/div/p/a[1]',
'作者':'/html/body/div/div/div[1]/div[1]/div/p/a[2]',
'正文':'/html/body/div/div/div[1]/div[1]/div/div[1]',#需要合并
'譯文':'/html/body/div/div/div[1]/div[2]/div[2]/p[4]',#需要合并
'注釋':'/html/body/div/div/div[1]/div[2]/div[2]/p[4]',
'賞析':'/html/body/div/div/div[1]/div[3]/div[2]/p[%d]',
'創作背景':'/html/body/div/div/div[1]/div[4]/div[2]/p',
'關于詩人':'/html/body/div/div/div[2]/div[2]/div[2]/p'}
Xpath_keys=['標題', '朝代', '作者', '正文','譯文', '注釋', '賞析', '創作背景','關于詩人']
最后獲得的詩也用字典存盤,爬取一首詩的完整代碼
import requests
from lxml import etree
url='https://www.xungushici.com/shici/1' #輸入我們的url
get = requests.get(url).text # get(url) 得到我們的網頁, text將源網頁轉化為字串
selector = etree.HTML(get) # 將原始碼轉換為xpath可以識別的TML格式
Xpath={'標題':'/html/body/div/div/div[1]/div[1]/div/h3',
'朝代':'/html/body/div/div/div[1]/div[1]/div/p/a[1]',
'作者':'/html/body/div/div/div[1]/div[1]/div/p/a[2]',
'正文':'/html/body/div/div/div[1]/div[1]/div/div[1]',#需要合并
'譯文':'/html/body/div/div/div[1]/div[2]/div[2]/p[4]',#需要合并
'注釋':'/html/body/div/div/div[1]/div[2]/div[2]/p[4]',
'賞析':'/html/body/div/div/div[1]/div[3]/div[2]/p[%d]',
'創作背景':'/html/body/div/div/div[1]/div[4]/div[2]/p',
'關于詩人':'/html/body/div/div/div[2]/div[2]/div[2]/p'}
Xpath_keys=['標題', '朝代', '作者', '正文','譯文', '注釋', '賞析', '創作背景','關于詩人']
content={}
for i in range(9):
if i in [3,4,5]:
ls=[]
ls=selector.xpath('/'+Xpath[Xpath_keys[i]]+'/text()')
content[Xpath_keys[i]] = ''.join(ls)
elif i==6:
ls=[]
for j in range(1,17):
path='/html/body/div/div/div[1]/div[3]/div[2]/p[%d]'%j
ls+=selector.xpath('/'+path+'/text()')
content[Xpath_keys[i]] = ''.join(ls)
else:
content[Xpath_keys[i]] = selector.xpath('/'+Xpath[Xpath_keys[i]]+'/text()')[0]
print(content)

可以看到已經爬取成功了
現在就考慮批量爬取了
urls=['https://www.xungushici.com/shici/%d'%p for p in range(1,20001)]#用串列生成運算式批量產生鏈接
用串列生成運算式批量產生鏈接,因為不同的頁面的鏈接就最后一個數字不同
因為不是每個鏈接都是能爬取成功的,所以用try except捕捉例外
import requests
from lxml import etree
ls1=[]
k = 0
p = 0
for count in range(0,20000):
try:
get = requests.get(urls[count]).text # get(url) 得到我們的網頁, text將源網頁轉化為字串
selector = etree.HTML(get) # 將原始碼轉換為xpath可以識別的TML格式
Xpath={'標題':'/html/body/div/div/div[1]/div[1]/div/h3',
'朝代':'/html/body/div/div/div[1]/div[1]/div/p/a[1]',
'作者':'/html/body/div/div/div[1]/div[1]/div/p/a[2]',
'正文':'/html/body/div/div/div[1]/div[1]/div/div[1]',#需要合并
'譯文':'/html/body/div/div/div[1]/div[2]/div[2]/p[2]',#需要合并
'注釋':'/html/body/div/div/div[1]/div[2]/div[2]/p[4]',
'賞析':'/html/body/div/div/div[1]/div[3]/div[2]/p[%d]',
'創作背景':'/html/body/div/div/div[1]/div[4]/div[2]/p',
'關于詩人':'/html/body/div/div/div[2]/div[2]/div[2]/p'}
Xpath_keys=['標題', '朝代', '作者', '正文','譯文', '注釋', '賞析', '創作背景','關于詩人']
content={}
content['pome_id']=count+1#將頁面鏈接最后的數字保存
for i in range(9):
if i in [3,4,5]:
ls=[]
ls=selector.xpath('/'+Xpath[Xpath_keys[i]]+'/text()')
if i==3:
content[Xpath_keys[i]] = '\n'.join(ls)
else:
content[Xpath_keys[i]] = ''.join(ls)
elif i==6:
ls=[]
for j in range(1,17):
path='/html/body/div/div/div[1]/div[3]/div[2]/p[%d]'%j
ls+=selector.xpath('/'+path+'/text()')
content[Xpath_keys[i]] = ''.join(ls)
else:
content[Xpath_keys[i]] = selector.xpath('/'+Xpath[Xpath_keys[i]]+'/text()')[0]
flag = True
for i in range(9):
if len(content[Xpath_keys[i]].split()) == 0:
flag = False
if flag:
k += 1
ls1.append(content)
print("下載的數量:%d 詩的編號%d"%(k,content['pome_id']))
except:
p+= 1
print("pass:%d"%p)
pass
效果圖:(機子慢,這個代碼跑了將近一個小時)

至此就將所有古詩都進行爬取了,但是只是存進了串列ls1中,并沒有下載下來,下一步就是將串列中的資料存入excl中,采用xlwt+pandas
import xlwt
import pandas as pd
def export_excel(export):
#將字典串列轉換為DataFrame
pf = pd.DataFrame(list(export))
#指定欄位順序
order = ['pome_id','標題', '朝代', '作者', '正文','譯文', '注釋', '賞析', '創作背景','關于詩人']
pf = pf[order]
columns_map = {
'pome_id':'pome_id',
'標題':'標題',
'朝代':'朝代',
'作者':'作者',
'正文':'正文',
'譯文':'譯文',
'注釋':'注釋',
'賞析':'賞析',
'創作背景':'創作背景',
'關于詩人':'關于詩人'
}
pf.rename(columns =columns_map ,inplace = True)
#指定生成的Excel表格名稱
file_path = pd.ExcelWriter('name7.xlsx')
#替換空單元格
pf.fillna(' ',inplace = True)
#輸出
pf.to_excel(file_path,encoding = 'utf-8',index = False)
#保存表格
file_path.save()
if __name__ == '__main__':
#將分析完成的串列匯出為excel表格
export_excel(ls1)
至此資料準備階段基本完成了(需要最后的資料的可以告訴我一下)
太晚了,之后再寫吧,整理一下發現要用到的東西也是挺多的
下一篇應該是將資料匯入進資料庫
基于知識圖譜的古詩詞推薦(python+爬蟲+mysql+neo4j)(二)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/273247.html
標籤:python
