{"id":15665883,"url":"https://github.com/kingname/sourcecodeofbook","last_synced_at":"2025-04-05T16:08:48.482Z","repository":{"id":37285957,"uuid":"151067436","full_name":"kingname/SourceCodeOfBook","owner":"kingname","description":"《Python爬虫开发 从入门到实战》配套源代码。","archived":false,"fork":false,"pushed_at":"2022-11-04T19:38:41.000Z","size":89245,"stargazers_count":363,"open_issues_count":5,"forks_count":127,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-29T15:07:39.721Z","etag":null,"topics":["python","python3","requests","scrapy","webcrawler"],"latest_commit_sha":null,"homepage":"https://item.jd.com/12436581.html","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kingname.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-01T09:54:06.000Z","updated_at":"2025-03-26T03:40:42.000Z","dependencies_parsed_at":"2023-01-21T10:35:16.664Z","dependency_job_id":null,"html_url":"https://github.com/kingname/SourceCodeOfBook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingname%2FSourceCodeOfBook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingname%2FSourceCodeOfBook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingname%2FSourceCodeOfBook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingname%2FSourceCodeOfBook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kingname","download_url":"https://codeload.github.com/kingname/SourceCodeOfBook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247361691,"owners_count":20926643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","python3","requests","scrapy","webcrawler"],"created_at":"2024-10-03T13:56:15.013Z","updated_at":"2025-04-05T16:08:48.457Z","avatar_url":"https://github.com/kingname.png","language":"Python","readme":"# 《Python爬虫开发 从入门到实战》配套源代码\n\n## 购书地址：\n\n* 京东：[https://item.jd.com/12436581.html](https://item.jd.com/12436581.html)\n* 当当：[http://product.m.dangdang.com/25349717.html](http://product.m.dangdang.com/25349717.html)\n* 亚马逊：[https://www.amazon.cn/dp/B07HGBRXFW](https://www.amazon.cn/dp/B07HGBRXFW)\n\n## 我的公众号\n\n![](https://kingname-1257411235.cos.ap-chengdu.myqcloud.com/wechatplatform.jpg)\n\n# 如果你不知道做什么，那就学一门杂学吧\n\n## 序言\n\n这篇文章没有代码，请放心阅读。\n\n多年以后，面对人工智能研究员那混乱不堪的代码，我会想起第一次和S君相见的那个遥远的下午。那时的B公司，还是一个仅有6个人的小团队，Mac和显示器在桌上依次排开，大家坐在一起，不需要称呼姓名，转过脸去，对方就知道你在和他说话。一切看起来都那么美好，我们所有人，都希望自己和这个公司能够一起成长。\n\n彼时S君刚从加拿大回来，老板把他介绍给我们，于是S君作为数据产品经理跟我有了项目上的接触。\n\n创业公司里面，每一个人都需要会很多的技艺，于是S君开始自学Python。\n\n有一天，S君问我：“你玩MineCraft吗？“\n\n“玩，但我更喜欢在B站上看别人的世界。”我答道。\n\n“我觉得我现在写程序，像是在玩我的世界。”S君笑着说道。\n\n“是不是觉得你已经掌握了Python的基本语法，看着别人把Python用的溜溜转，而你自己却不知道用它来做什么？”\n\n“是这样的，你懂我。”\n\n“那你学一门杂学吧。”\n\n于是S君被我诱拐过来跟我一起写爬虫。\n\n后来，S君离开了B公司。\n\n三个月后，我也离开了。\n\n从此，我们再也没有见过。\n\n## 编程最重要的能力是变通\n\nS君是一个老实孩子。\n\n在开发一个爬虫的过程中，网站接口返回给他的数据看起来是JSON格式，于是他就用Python自带的JSON库去解析。结果解析失败了。因为这些所谓的看起来像JSON的东西，竟然没有双引号。\n\n难道是JSON的超集？S君一通搜索，发现用YMAL库也许可以解析这种数据。于是安装YMAL库，一解析又报错。\n\n难道这些数据直接就是Python的字典？于是S君用上了邪恶的eval。又报错，因为里面有null和小写的true。\n\n“你为什么不试一试直接用正则表达式呢？”我对S君说。\n\n“靠！”S君一拍桌子，旁边的老板吓得把搪瓷杯子里面的快乐水洒在了白衬衣上。\n\n然后S君用正则表达式花了10秒钟结束了战斗。\n\n## 写爬虫与三峡大坝\n\n有一天，S君兴冲冲地跑来跟我说：“我体会到三峡大坝的伟大功能了！”\n\n“你是爬虫工程师还是水利工程师？”\n\n“你知道吗，不管上游的水势多么凶猛，从大坝出来以后总是安全而稳定。”S君并没有回答我的问题，而是自顾自地说道。\n\n“原来你开始用Kafka。不错，孺子可教。”\n\nS君吐了一下舌头：“还是师傅教导有方。”\n\n前不久，S君的爬虫刚刚达到了日产数据千万条的目标。然而他只高兴了一天。因为他发现，数据写到数据库以后，读起来很麻烦。\n\nS君有多个数据分析的系统需要从数据库里面读取爬虫爬好的数据，但是从每天千万量级的数据中寻找特定的数据是一个很慢的过程。如果程序遇到异常导致崩溃，又得从头开始读。\n\nS君问我：“现在我每一个数据分析的脚本都要从数据库里面读一次数据，做了太多重复的工作，单机单节点的数据库快要撑不住了。我是不是要去学习分库分表搭建集群啊？”\n\n我告诉S君：“这个后面你自然是需要去做的。但现在，你可以先试一试Kafka，我已经搭建好了一个Kafka的集群了，你这样使用……”。\n\n后来，S君让所有爬虫把爬到的数据到直接送进了Kafka，然后再从Kafka里面读数据出来，一个Group用来备份原始数据，一份Group用来生成中间表，一份Group用来监控报警，一份Group用来绘制DashBoard。无论爬虫塞给Kafka的数据有多少，有多快，从Kafka读数据的地方都能按照自己的节奏来消费和使用。\n\n## 既然收集了数据就要让它发光发热\n\nS君在加拿大留学时学的专业是金融数学和统计。所以他对数据分析也很有兴趣。在他爬虫收集的数据够用以后，我跟他讲了如何使用Pandas来分析数据。\n\nS君把他分析的酒店价格变化数据给分享给了我们。不愧是金融+数学+统计学背景的高级知识分子 + 超级强大的Pandas + 超级好用的Jupyter。这份数据不仅完美再现了过去一年的价格走势，还预测了未来的任何变化，多达四十六张图表似乎穷尽了所有的组合。\n\n## 草木竹石皆可破敌\n\nS君曾经遇到过一个特别简单的电商网站。页面几乎像素级抄袭淘宝，但是完全没有任何反爬虫的机制。以S君的水平，从审查元素，到开发完成，仅仅用了半个小时。爬虫安全平稳又顺利地运行了三个星期。\n\n然后，有一天早上，爬虫死掉了。\n\nS君用尽毕生所学，无法再从这个网站上爬到任何有价值的信息。这个网站似乎请来了一个机器行为对抗的大神级人物。人用浏览器一点问题都没有，但S君的任何隐藏爬虫的手段都被轻易识破。\n\nS君找到我：“师傅，这个网站我搞不定。”\n\n“你能搞定。动动脑子。”\n\n“我会的所有技术都用上了，完全看不出破解他反爬虫机制的方法。”S君已经失去了信心。\n\n“那就，不要用技术去对抗。用你的脑子。”\n\nS君抱着显示器用头一遍一遍的撞。\n\n我问S君：“你有没有思考一个问题，这个网站模仿了淘宝的皮，却又毫无反爬虫机制。你觉得他的老板是一个什么样的人？你听过那个段子吗？”\n\nS君突然一跃而起：“我给你一万元，你帮我做一个网站吧。你想要什么样的网站？很简单，就淘宝那样的。你是说这个段子吗？”\n\n“对。”\n\nS君突然之间荣光焕发：“有办法了！”\n\n只见S君重新在浏览器打开了这个网站，找到了客户服务热线。电话一拨通他就开始一通污言秽语骂起来：“……你们网站到底在搞什么？为什么今天一会能登录一会不能登录？找你们老板来！我来教他怎么做网站！……”\n\n半小时以后，网站反爬虫机制全部解除。\n\n此刻，S君面向西面双手合十，自言自语：“兄弟，对不起了，只有让你来背这个锅了。”\n\n\n## 你小学上课传过纸条吗\n\n“我现在能体会那些半路拦截纸条的人是什么心态了。”这是S君第一次使用Charles时对我说的话。\n\n从此以后，我很少看到S君分析网页了。因为他学会了在爬虫开发的过程中，首先通过中间人攻击技术分析微信小程序和手机App。这种方式往往能够直接获得数据，拿到数据以后就能直接储存，再也不用写烦人的XPath或者长的跟表情符号一样的正则表达式了。\n\n有一天，我在玩一个网页版的黑客解密游戏，在网页上寻找某个地方隐藏起来的密码，然后输入每一关的回答框中，答对才能进入下一关。\n\n游戏有12关，而我卡在了第6关。只见S君拿着电脑走到我面前，指着第12关的通关页面跟我炫耀。\n\n“你是不是用MITMProxy替换了这个网站的Js文件？”\n\n“果然还是瞒不过师傅你啊。”\n\n“你拦截了别人的纸条，做了修改，然后又叠好继续传下去，你有考虑过发纸条的人和收纸条的人的感受吗？”\n\n“我小学时候不传纸条，都是妹子直接约我的。”\n\n## 加密？不存在的\n\n“前端没有秘密”。S君在成功逆向了一个网站的Js文件以后如是对我说。\n\n“那是因为这个网站的Js代码就赤裸裸地放在你面前，完全没有混淆。”我对S君说道。\n\n“不怕，我可以用Node.js来运行混淆过的代码。我已经搭建好Node.js服务了，只要把Js代码传进去，他就会把结果给我返回回来。”S君对此似乎一脸自行。\n\n“你什么时候学会的Node.js？”\n\n“这不是师傅你说过技多不压身吗？既然做爬虫需要动JavaScript，那我顺手就把Node.js给学了。”S君毫不畏惧的表情，似乎证明他已经猜透了我要问什么。\n\n“那如果目标没有网站，只有App呢？”\n\n“不怕，Android 逆向工程我也顺便研究了一点。Java我也看得懂。”\n\n“看来这些已经不需要我再教你了。”\n\n## 我一根指头就能捏死你，但我不想伤害你\n\nS君有一天问我：“假设你现在在小学课堂上，前面的同学让你把纸条传给后面的女生，你会怎么做？”\n\n我说：“查看复制/修改删除/拦截丢弃”。\n\nS君嘿嘿一笑：“比如说，前后三次的纸条分别为‘听说你奶奶生病了，我们周末一起去看望她吧‘，’今晚我爸妈不在，去我家玩吗？’， ‘我刚拿到这个月压岁钱，老师一下课我们就去吃好吃的。’”\n\n我说：“女孩漂亮的话，我改一下第二张纸条，改成‘今晚我爸妈不在，我们一起去青南家玩吗？’”。\n\nS君露出了嫌弃的眼神：“师傅，你可是说过你最讨厌技术含量低的事情啊，你涂改了纸条，别人不会发现？你笔迹都不一样啊！”。\n\n我问S君：“那你有何高见？”\n\nS君抬头仰望这窗外的天空：“如果是我，那么我会临摹第一张纸条上面的`生病了` `去看望` `她` `我`，第二张纸条上面的`爸妈`，第三张纸条上面的`拿` `钱` `老师`这些字的笔迹。然后改换一下顺序就变成了：`爸妈，我老师生病了，我拿钱去看望她`。最后我把这张伪造的纸条拿去找写纸条的那个同学他爸妈要钱。”\n\n“我猜，你想用中间人攻击截取别人的Cookies，然后用这些Cookies偷偷登录网站，进行你的不可告人的目的。”\n\nS君笑道：“哈哈哈，我想想都害怕。但是每当我想到，我拥有一种可怕的力量，而我还能控制住这种力量。我就知道我和街上的普通人不一样了。”\n\n## 你肯定薅了直播答题的羊毛吧\n\n去年年底的直播答题着实火了一把。那个时候，我和S君分开已经有一段时间了。我相信，在全民答题的每一个夜晚，S君的电脑上一定连着不少于六台安卓手机。这些手机运行着不同的答题平台，能够自动读取屏幕上的问题并自动选择答案。\n\n我把安卓自动化测试技术教给S君，本来是让他结合爬虫，实现群控从而抓取一些难以处理的数据，但我相信他肯定会用来答题。\n\n变通，这一点他学的越来越好了。\n\n只希望他不要成为羊毛党。\n\n## 后记\n\n后来，我再也没有见过S君这样有趣的人。所以我把我教给S君的东西，写成了一本书：《Python爬虫开发 从入门到实战》，现在已在京东，当当与亚马逊上架。希望你也能变成S君一样有趣而又厉害的人。\n\n爬虫是一门杂学。因为在一个完整的开发过程中，需要涉及到的知识可以包括但不限于：Python，HTML，JavaScript，正则表达式，XPath，数据库，Redis，消息队列，Docker，ELK，Hadoop，数据分析，ETL，中间人攻击，自动化测试技术，可视化……\n\n这其中的任何一项，在一个大公司里面都可以让很多人来做。\n\n爬虫开发，就像这篇文章里面反复出现的一个词：变通——只要能够获得数据，任何技术都可以使用。所谓草木竹石皆可为剑。爬虫不应该是一个枯燥的一成不变的模式化的工作。而是一个充满了创意和挑战，能够让旁观者大呼“我X还能这样搞”的工作。\n\n爬虫开发，绝对不仅仅是Scrapy，PySpider，requests这些框架或者库的使用。所以在这本书里面，我也刻意减少了框架使用说明的部分，而把重点放在了各种突破反爬虫机制或者使用变通的方法绕过反爬虫机制的方法论和实践中。\n\n通过学习爬虫，你最后不一定选择爬虫工程师这个岗位，但是在学习爬虫的过程中，你将会接触到的各种工具，方法，服务组件，都会在你以后的生活和工作中帮到你，让你知道，在遇到一个问题的时候，解决方法在哪个地方。\n\n最后，我自己,我在网络上的名字叫做青南或者kingname（青南的音译）。2014年加入LCTT，2015年作为极客学院爬虫课程讲师，开设的爬虫开发课程，受众超过10万。现在在网易游戏担任高级数据挖掘工程师。\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkingname%2Fsourcecodeofbook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkingname%2Fsourcecodeofbook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkingname%2Fsourcecodeofbook/lists"}