python爬虫百度文库 | 您所在的位置:网站首页 › python爬取百度文库代码 › python爬虫百度文库 |
首先先分享下github这篇文章吧,参考了部分代码,但我想做一个很详细的解读。新版百度文库爬虫 · Jack-Cherish/python-spider@3c5480dgithub.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) |
CopyRight 2018-2019 实验室设备网 版权所有 |