python爬虫百度文库源码_Python爬取百度文库学习
首先先分享下github這篇文章吧,參考了部分代碼,但我想做一個很詳細的解讀。新版百度文庫爬蟲 · Jack-Cherish/python-spider@3c5480d?github.com
首先,我想自動化打開百度文庫的頁面(其實這一步,并不需要,經實踐得知)。
不過,我覺得這一步算是初級的對selenium理解,希望對大家有所幫助。
第一步的流程:自動化打開百度文庫網頁 -> 將窗口下滑到“繼續閱讀”的按鈕處 -> 自動點擊 -> 顯示完整頁面。
def auto_page_search(url):
print('開始自動查詢網頁')
browser = webdriver.Chrome()
# browser.get('https://wenku.baidu.com/view/dcfab8bff705cc175527096e.html')
browser.get(url)
print('等待5秒')
time.sleep(5)
# 下面這個語句并不是查找“繼續閱讀”按鈕所在位置,而是更上面的元素,因為按照原本元素位置滑動窗口會遮擋住,大家可以試一試
eles = browser.find_element_by_xpath('//*[@id="html-reader-go-more"]/div[1]/div[3]/div[1]')
browser.execute_script('arguments[0].scrollIntoView();', eles)
print('等待2秒')
time.sleep(2)
#點擊“繼續閱讀”按鈕
browser.find_element_by_xpath('//*[@id="html-reader-go-more"]/div[2]/div[1]/span/span[2]').click()
print('已顯示文檔所有內容')
接著,欸我們就想著定義一個可以抓取網頁源代碼的函數,以便于我們后面的爬取,這個函數很重要。
def fetch_url(url):
''':return: 網頁源代碼'''
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}
session = requests.session()
sourse = session.get(url, headers=headers).content.decode('gbk')
return sourse
這里用的是 session 方法,不過我認為直接 request.get 也 OK ,看個人喜好了。
doc ,txt ,pdf ppt 的爬取方式有些差異,而且都很奇怪。
先介紹 txt 格式的文庫如何爬取:
我們打開一個文檔,如下:
好吧我們現在話不多說,直接打開開發者工具。
大家不能被 Element 中顯示有文檔的內容,就想著直接用什么正則、xpath等暴力爬取源代碼了,這里顯示的內容,是經過一系列渲染以后,展示在我們面前的,右鍵打開網頁源代碼,會發現根本沒有什么文字內容。
那我們看一下真正的文字內容在哪里?很難找,就在下面的加載文件里:
敢信?沒錯就是這么長一個文件,URL 中的紅線(可能沒標好)顯示的部分,是需要我們獲取的,比如 md5 ,rsign 等,然后構成這個 URL 。
可能有人問了,我們都能找到這個文件,為什么不直接用呢?偏要找到那些 md5 、rsign 。因為我們是希望直接輸入百度文檔的地址,就直接自動生成 txt 文件,而不是每一次費很大勁找到這個加載文件。當然如果不嫌麻煩的話你也可以這樣做。
所以我們應該找到 network 中第一個文件,它里面顯示的就是網頁的源代碼。找到下圖。
獲取其中的 title 、docId 、docType 。代碼如下:
def get_Id(sourse):
Id=re.findall(r"docId.*?\:.*?\'(.*?)\'\,",sourse)[0]
return Id
def get_Type(sourse):
Type=re.findall(r"docType.*?\:.*?\'(.*?)\'\,",sourse)[0]
return Type
def get_Title(sourse):
Title=re.findall(r"title.*?\:.*?\'(.*?)\'\,",sourse)[0]
return Title
我們獲取這些東西干啥呢?當然是獲取 rsign 等信息了。
接下來我們要獲取的信息在下面這個加載文件里:
不過這個鏈接我們最后的一部分可以不要,我們利用正則表達式獲取 rsign 等信息,就可以拼接起正文內容的鏈接。
流程差不多就是上面這樣,最后就是獲取正文內容。
正文內容是 json 格式的,需要改變一些換行符等排版,接著保存就好,代碼如下:
def parse_txt(Id):
''':param Id: 之前爬取的 docId'''
url1='https://wenku.baidu.com/api/doc/getdocinfo?callback=cb&doc_id={}'.format(Id)
content1=fetch_url(url1)
md5=re.findall('"md5sum":"(.*?)"',content1)[0]
pn=re.findall('"totalPageNum":"(.*?)"',content1)[0]
rsign=re.findall('"rsign":"(.*?)"',content1)[0]
url2 = 'https://wkretype.bdimg.com/retype/text/' + Id + '?rn=' + pn + '&type=txt' + md5 + '&rsign=' + rsign
content2=json.loads(fetch_url(url2))
result=''
for items in content2:
for item in items:
result=result+item['c'].replace('\\r','\r').replace('\\n','\n')
return result
#保存為 txt 文件
def save_file(filename, content):
with open(filename, 'w', encoding='utf-8') as f:
f.write(content)
print('已保存為:' + filename)
txt 文檔基本就上面這樣了,有的 url 鏈接可以去掉部分數字,所以看起來比原有的 url 更短。
接著是 doc 文件:
doc 的爬取借鑒了開頭高手的代碼,所以這里只想做個解讀。
def parse_doc(content):
result = ''
url_list = re.findall('(https.*?0.json.*?)\\\\x22}', content)
url_list = [addr.replace("\\\\\\/", "/") for addr in url_list]
for url in url_list[:-5]:
content = fetch_url(url)
y = 0
txtlists = re.findall('"c":"(.*?)".*?"y":(.*?),', content)
for item in txtlists:
if not y == item[1]:
y = item[1]
n = '\n'
else:
n = ''
result += n
result += item[0].encode('utf-8').decode('unicode_escape', 'ignore')
return result
下面一步一步解釋。
這個函數需要輸入一個 content ,這個東西是代表網頁源代碼,在這里就是文檔所在位置的網頁源代碼。
好的我們看下面這一句:
url_list = re.findall('(https.*?0.json.*?)\\\\x22}', content)
這個東西運行完,實際就是找到了下面這些內容:
要這些東西干嘛?我們看到下一個句子:
url_list = [addr.replace("\\\\\\/", "/") for addr in url_list]
就變成了一個個可以點擊的 url 地址了,實際上對應的就是 Network 中加載文件的下圖:
但是我們發現下面的一句:for url in url_list[:-5]
為什么只循環到倒數第五個呢?這里我們首先確保點擊了“繼續閱讀”按鈕,查找相關文件,發現最后一個符合要求的加載文件正好是 url_list 列表對應的倒數第五個元素。
說明 url_list 中最后面的元素并不是我們想要的東西。
后面的代碼就是關于如何爬取 json 格式的字符串了以及保存(doc 文檔同樣在這里以 txt 文件保存),就不多解讀了。
以及百度文庫的 PPT PDF 爬取實在不想寫了,模式和爬取 txt 文檔類似。
說實話,感覺百度文庫的爬取實在有點讓人摸不清頭腦,只求看懂以及思維的跳躍能夠跟上。也算記錄了一種心得吧。
最后附上 main()函數。
def main():
url1 = input('請輸入需要爬取的文庫地址:')
auto_page_search(url1)
sourse=fetch_url(url1)
Id=get_Id(sourse)
Type=get_Type(sourse)
Title=get_Title(sourse)
if Type=='txt':
result=parse_txt(Id)
save_file(Title+'.txt',result)
elif Type=='doc':
result=parse_doc(sourse)
save_file(Title+'doc',result)
總結
以上是生活随笔為你收集整理的python爬虫百度文库源码_Python爬取百度文库学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt ftp 文件上传工具开发
- 下一篇: Python学习1——Python中的