
考虑到, 在目前而言, 大部分的小伙伴他们使用的主要原因是为了爬虫这个东西, 那么为了更好地帮助到大家把爬虫这个知识给巩固起来, 以及对爬虫的理解进行加深, 所以最终选择了爬取百度文库作为我们的目标。关于这一方面, 我们不再赘述过多的言语, 随即转入接下来的环节。把那个 TXT、DOCX 里面的内容, 通过网络给爬取出来, 并且把它保存起来。这是小编已经准备完毕的基础学习资料, 大家只需要关注一下, 再转发给其他人, 并且私信联系小编并输入数字01这样的内容就可以免费地把这些资料领取走。在去爬取各种东西的时候, 我们要先把需要爬取的数据, 确定一下它是不是异步加载的。只要是异步加载的数据, 直接去爬取网页的话, 就是爬不到的。要知道是不是异步加载其实是很简单的事情, 大家可以用对网页发起请求这种方式, 来看看请求返回的具体内容是什么就完全可以了。url https://wenku.baidu.com/view/4e29e5a730126edb6f1aff00bed5b9f3f90f72e7.html?rec_flagdefaultheader {User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36}res requests.get(url , headers header)res.text很明显, 返回过来的内容是根本就不是我们所希望获取到的内容基于人们日常的正常逻辑, 我们就能够对这一情况做出判断, 认定该网页采用了异步加载的技术方式来传递信息。不过从正常的认知出发, 若是网页所呈现的内容属于异步加载类型的话, 那么直接去执行百度搜索这个操作, 是没办法搜查到该网页内部所含有的具体内容的, 但十分明显的事实是, 我们每一次通过使用百度搜索工具来执行查询, 往往都可以直接定位到文库中所保存的那些文本内容。如下:那这就挺有意思了, 直接发起请求是获取不到网页内容的, 为什么通过百度搜索可以找到关键肯定在于百度搜索上面。在这个时候, 我们通过查看和搜寻信息的方式, 最终弄明白了当前存在的主要矛盾点到底是在哪里, 也就是问题最大的一块儿地方是在我们的这一方面。在进行网页爬取工作的时候, 通常是把特定的标识作为身份证来使用的, 其目的是让网页端无法判断出我们实际上是爬虫程序如果选择不添加这个标识的话, 那么网页就会直接识别出我们是爬虫行为, 进而拒绝提供访问服务。如果我们再深入去了解一下那个识别机理的话, 就发现有一个东西, 叫做 Robot 协议。它规定了什么样的人可以访问网页内部的内容, 除了被指定为允许访问的人以外其他的人都是无法请求页面内容的。比如说, 百度文库的协议就是下面这样的情况:User-agent: BaiduspiderDisallow: /w?Disallow: /search?Disallow: /submitDisallow: /uploadDisallow: /cashier/而我们要进行爬取处理的那些内容, 它所对应的网址格式就是。这说明我们有可能拿到文库里的内容了。我们的推测是这样的, 因为大家在百度搜索的时候需要根据文本内容来选择匹配的搜索选项, 所以系统就放行了。因此我们尝试伪装 UA 为url https://wenku.baidu.com/view/4e29e5a730126edb6f1aff00bed5b9f3f90f72e7.html?rec_flagdefaultheader {User-agent: Googlebot}res requests.get(url , headers header)res.text果然和我们预料的一样, 没有搞错。我们最终把那个目标给拿到了手。既然现在已经成功拿到了网页对应的正确的那些源代码, 所以接下来的时候就是要去解析那个网页, 然后从中获取到想要的具体的内容。市面上存在许多可以被用来解析网页源代码的库文件, 在此处具体的选择情况是, 我们采用的是。plist []soup BeautifulSoup(r, html.parser)plist.append(soup.title.string)for div in soup.find_all(div, attrs{class: bd doc-reader}):plist.extend(div.get_text().split(\n))plist [c.replace( , ) for c in plist]plist [c.replace(\x0c, ) for c in plist]plist整个解析是特别简单的, 全都是非常标准的操作方式。在这里就不多加叙述了, 最终的效果如下:当然爬取到东西了只是万里长征的第一步, 就这样是肯定不行的, 我们还需要将爬取的内容保存起来, 通常是保存为 txt 文件。file open(test.txt, w,encodingutf-8)for str in plist:file.write(str)file.write(\n)file.close()为了达到一个更加美观的样子, 我们在此处选择了使用 -docx 这个库, 来把内容进行保存操作, 具体的格式是 docx 文件。with open(test.txt, encodingutf-8) as f:docu Document()docu.add_paragraph(f.read())docu.save(test.docx)对PPT文件和PDF文件进行爬取操作, 并且把它们保存到本地。基于以前的经验和教训, 我们在执行爬取任务的时候, 一开始就先试着去用那种爬取TXT格式以及DOCX格式的办法来进行操作, 以此来试探并验证到底能不能抓取到里面的内容。url https://wenku.baidu.com/view/a4ac1b57dd88d0d232d46a0f.html?frsearchheader {User-agent: Googlebot}res requests.get(url , headers header)res.text非常遗憾, 实际情况是没能实现访问动作。原因其实仔细想来也很简单, 这是因为直接在百度搜索框里面去搜索的时候, 是没办法直接搜到 PPT 或者 PDF 的内容的。那么很显然PPT 和 PDF 是通过异步的方法进行内容加载的关于异步加载而来的那些数据, 我们在平常的时候, 一般地都会去采取下面这一些应对的方式和方法, 这种策略呢, 总共有两种。1、第一个办法就是直接去找到那个来发起异步请求的接口, 然后自己来专门构造好要发送的请求头, 接着再去发起网络请求这个动作。2、第二个是借助这种自动化测试工具, 去执行数据采集的操作。在寻找百度文库的接口的这一件事情上, 过程是显得非常困难的, 同时呢, 对于那些请求头的构造工作来说也是颇为繁琐的, 我们进行了长时间的摸索和查找, 可是终究没能找到让自己完全满意的结果。因此, 针对这次数据采集的任务, 我们选择了采用第二种方案的方式来进行操作, 也就是具体使用了像这些自动化测试工具来进行相关的处理。我们在这里需要去下载这个插件, 当然啦, 这里的情况是一般默认大家使用的是浏览器这个软件, 如果你们使用的不是这个, 而是其他的一些浏览器, 比如说还有一些其他的等等这样的情况, 那么可以直接在网上去寻找那些相应的东西就可以了。这里给出的这个文件的实际的连接, 你可以去那个地方找到并且下载。大家一定要去下载那个, 和你自己的这个浏览器版本是完全一致的这样的东西, 不然的话, 程序在运行的时候是会报错的。我们先不急於立刻着手展开抓取操作, 我们应当率先尝试去执行一下相关的调用处理。import requestsfrom selenium import webdriverurl frsearchdriver webdriver.Chrome(rF:\driver\chromedriver.exe)driver.get(url)怎么样, 是不是浏览器已经自动打开了? 现在我们来尝试进行输出这个动作如此便可以看见网页的正确源代码已经在里面。现在我们仔细地去看一下源代码, 这样就可以看到, 我们所需要的内容就存在于下面这个位置。现在正确的源代码已经出现了, 内容所处的具体位置也已经清楚了, 所以就直接进行解析处理以及执行网络爬虫抓取操作就可以了。想得还真挺美, 在经过了一番这样的爬取操作之后, 又进一步去对抓到的内容进行了解析, 接下来让我们仔细瞧瞧, 到底是不是已经成功地把内容给爬取下来了。from lxml import etreeimport rehtmletree.HTML(driver.page_source)linkshtml.xpath(//div[classreader-pic-item]/style)part re.compile(rurl[(](.*?)[)])qa.join(links)zpart.findall(qa)z我们能够清楚地了解到, 实际上我们仅仅爬取了 3 张 PDF 文件, 而那些其他的文件则完全没有被进行爬取。这是为什么呢这是百度文库为了防止大家去爬专门设置的一个小机关返回百度文库这个页面以后, 我们要去仔仔细细地查看它的源代码内容, 从本质上来说, 我们能够观察到这样一个事实, 随着网页呈现形态的变化不停发生, 源代码里面的东西也在不断地发生着改变, 每一次去获取的时候, 能够看到的只有3张这种类型图片对应的url链接地址信息。在这个地方页码数是存在一定规律的, 如果是处于第二页的话那么对应的图片就是 1 接着是 2 再接着 3, 而如果是第三页的情况那么图片就变成了 2, 然后是 3, 最后是 4。那么, 我们心中的疑惑就一下子得到了解决, 接下来的具体操作方式其实非常简单, 说白了, 就是需要不断地去进行换页的爬取工作而已。那, 下面要做的事情, 就是去实现那个换页的操作啊。这涉及到两个步骤, 首先是点击继续阅读, 然后是进行页面输入以实现换页。先把那个点击的活儿给办到, 具体的代码嘛, 就在这下面:button driver.find_element_by_xpath(//*[idhtml-reader-go-more]/div[2]/div[1]/span)button.click()driver.execute_script(arguments[0].click();, button)整个操作的全过程是需要通过这个技术手段来实施完毕的, 大家完全可以把这一条关键信息牢牢地记在心中, 那么等到未来的时候需要执行点击这个动作的时候, 就可以直接地使用它。接下来是关于输入页面实现换页这个部分, 因为这里头牵扯到的内容还是比较多的, 如果要细细拆开来看的话, 具体的操作步骤可以分成两块内容, 第一块是来获取总共有多少页的, 第二块则是按照顺序去一个一个地把页面输入完毕然后点击。import re# 寻找页面source re.compile(r/(.*?))number int(source.findall(driver.page_source)[0])# 输入页面并点击driver.find_element_by_class_name(page-input).clear()driver.find_element_by_class_name(page-input).send_keys(2)driver.find_element_by_class_name(page-input).send_keys(Keys.ENTER)如果小伙伴成功实现了上面的操作其实大体的爬取工作已经差不多了接下来就是保存我们的 PPT 和 PDF了因为在爬取PDF和PPT资料的时候, 我们获取到的是图片的源地址。所以我们就必须对这个地址发起请求。然后呢, 要把返回的内容以二进制的数据形式保存下来, 这样才能得到这张图片并把其存储起来。for m in range(3):pic requests.get(z[m]).content# 方法一# file open(f./照片/{m1}.jpg,wb)# file.write(pic)# file.close()# 方法二with open(f./照片/{m1}.jpg,wb) as f:f.write(pic)f.close()在此处, 特意给大家提一个醒, 这一点是非常关键的, 也就是在进行文件命名操作的时候, 务必要严格依照图片的排列顺序来完成相关设置工作, 其主要原因就在于此, 如果后续需要将相关文件保存转换成为 PDF 格式的话, 这种预先设定的次序是不可或缺的必要条件。在py文件所在的目录中, 大家就能看到被保存下来的图片。到了最后这一步, 大家就可以把这个图片保存成PDF格式的文件了。from PIL import Imageimport osfolderPath F:/TESTfilename testfiles os.listdir(folderPath)jpgFiles []sources []for file in files:if jpg in file:jpgFiles.append(file)tep []for i in jpgFiles:ex i.split(.)tep.append(int(ex[0]))tep.sort()jpgFiles[folderPath / str(i) .jpg for i in tep]output Image.open(jpgFiles[0])jpgFiles.pop(0)for file in jpgFiles:img Image.open(file)img img.convert(P)sources.append(img)output.save(f./{filename}.pdf,PDF,save_allTrue,append_imagessources)最后所达到的结果情况是这样子的, 也就是我们这边生成的这一个pdf类型格式的文件。上述的这些操作, 看起来是有点多, 也有点麻烦, 不过, 这其实并不是那样子的, 原因是绝大部分的操作都是固定的那一些样子, 对于大家来说, 唯一需要做的, 就是把它们记到非常熟练的程度。所谓的GUI制作, 其实是指图形用户界面制作。在图形用户界面这块工作上, 我们正在做一些更新的内容, 通过使用C#语言来编写一个较为简单的图形用户界面, 并且通过这个界面向爬虫程序所使用的代码进行调用操作。我在C# 项目中调用项目的时候, 我用了一个简单一点的方法, 就是直接用类去执行操作, 然后通过跑 .exe 这个动作, 来把代码给运行起来。public static void RunPythonScript(string sArgName, string py, string args , params string[] teps){Process p new Process();//(没放debug下写绝对路径)//string path C:\Users\zll\Desktop\baidu\CSharpCallPython\bin\Debug\ sArgName;// 获得python文件的绝对路径将文件放在c#的debug文件夹中可以这样操作string path System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase sArgName;//没有配环境变量的话可以像我这样写python.exe的绝对路径。如果配了直接写python.exe即可//p.StartInfo.FileName C:\Users\zll\AppData\Local\Programs\Python\Python37-32\python.exe;p.StartInfo.FileName py;string sArguments path;foreach (string sigstr in teps){sArguments sigstr;//传递参数}sArguments args;p.StartInfo.Arguments sArguments;p.StartInfo.UseShellExecute false;p.StartInfo.RedirectStandardOutput true;p.StartInfo.RedirectStandardInput true;p.StartInfo.RedirectStandardError true;p.StartInfo.CreateNoWindow true;p.Start();p.BeginOutputReadLine();p.OutputDataReceived new DataReceivedEventHandler(p_OutputDataReceived);Console.ReadLine();p.WaitForExit();}对输入的内容进行一个简单的判断, 看看它是不是百度文库的链接又或者是不是 .exe 这个格式的地址, 如果是的话就不管它, 不是的话就直接报错。if (!url.Contains(https://wenku.baidu.com/view/)){MessageBox.Show(请输入正确的百度文库网址);lbl_state.Text 请重新输入。;}else if (!py.Contains(python.exe)){MessageBox.Show(请输入正确的python.exe路径);lbl_state.Text 请重新输入。;}else{//输入参数列表String[] strArr new String[] { url, istxt };string sArguments src\wenku.py;//这里是python的文件名字RunPythonScript(sArguments, py, -u, strArr);if(result.Contains(0))lbl_state.Text 对不起爬取失败。;else if (result.Contains(1))lbl_state.Text 爬取成功;}鉴于用户界面这部分的构成相对较为简单明了, 所以在接下来的叙述之中也就暂时不做更加详尽细致的说明了。