爬取百度城市百科 by Python

同学拿到老师给布置的一个任务:

全国各地市的风俗习惯。具体到某个省的某个市。尽量用自动查询手段搜索百度百科,获取全国所有地市的简介和饮食、风俗习惯等。生成一张excel表格

感觉上像是要做一个爬虫,最后这个生成 excel 表格真的是无力吐槽了。。。之前虽然自己看过一些爬虫的教程文章,但是感觉这个事更多的时间是分析网页,解析 HTML ,然后将数据可视化的显示出来,于是一直没有动力去爬一个什么东西。这不,动力来了。

注:一不小心把这篇写成了记事文,而不像是个技术分享。。。

先看了下百度百科几个城市的页面,似乎结构性不强。大的城市文化饮食什么的介绍比较多,小一点的城市可能直接没有这个条目了。不过看要求上有提到城市简介,直接找百科第一段的内容还是比较简洁的。通过 Chrome 的审查元素,可以直接复制对应部分的 XPath,使用 python 的 lxml 库方便实现查找对应的部分。(其实这部分我没做。。。)

介于自己很懒,不会去把所有城市的页面分析一遍,然后再选取想要的部分,我就盯着百度百科的主页看了半天,于是发现了特色百科——城市百科这个东西。每个城市页面的 URL 是城市名的拼音,对也页面将美食、文化等进行了分类显示。这不就是绝好的资源嘛!

找到了爬取的资源,目的明确了,剩下的就是搞定要达到目的需要的工具了:

  • 所有城市的列表:这个是同学直接给我了,不过应该直接从百科里找也能找到。
  • 城市的拼音:发现这个 PyPinyin 的库,可以将汉字转换成拼音。看了下还有挺多功能。
  • 拼接 URL:因为城市百科的 url 直接是拼音,直接拼接字符串即可。但是前面提到的百科的搜索请求,则需要用到 urllib 库里的 urlencode 方法(python3中在 urlib.parse 里)。
  • 获取页面内容:额外的 requests 和官方的 urllib 都可以实现
  • 解析页面内容:当然是经典的 BeautifulSoup lxml 了,不过我最后似乎没怎么用
  • 输出结果:print 大法好!当然写入文件的,兼容 excel 的 csv 模块可以提供帮助。

任务就是这些内容,剩下的就是代码的拼接,以及繁琐的解析网页结构,寻找自己想要的部分了。接下来记点具体的步骤吧:

  1. 美食、文化等标签的切换,是通过 js 实现的,需要通过审查元素的 networking 去追踪请求的具体地址
  2. 发现请求的包括 type指代类别(文化、美食等)、limit限制、offset偏移(获取前多少条内容)以及一个 cityId(城市编号)。于是开始找这个编号。。。
  3.  搜索整个页面,只有一段 js 文本里包括这个 id ,可是 Python 怎么找 js 里的变量啊……
  4. 发现一个 Pyv8的库,通过 v8引擎,可以在 python 中实现和 js 脚本的交互,但是装不上。。。
  5. 于是用 bs4 匹配出来所有的 js 标签,然后找出来对应的一个(人眼看,手工写死),虽然知道这么不对,但是似乎想不到动态的方法了。。。(除非把所有 js 都找一遍)
  6. 用 string 自带的split 方法,用分号切分 js 语句,然后找到 cityId,再用等号分割一次,获取对应的 cityId
  7. 终于可以发请求了!直接对第二步找到的对应 API 地址发 get 请求,得到 json 字符串
  8. Python 自带 json 解析库。解析出来以字典存储。刚好方便查找对应的名称,描述等等,不过描述是带省略号的。。。
  9. 谁能告诉我为什么对应词条(比如美食下的北京烤鸭)的 URLid 用的属性名是:oldLemmaId?

说实话,我好想直接把代码粘上来,证明我真的做了。不过确实太难看了。。。我还是再改改吧,看看能不能再完善一些。花了一天的时间搞定这个,也是醉了,果然之前上手写的少。一写起来就又各种问题需要查。

PS:stackoverflow真是个好网站!

PSS:已知一些问题:

  • 原以为百科的页面都是/view/id.html 的结构,刚刚发现有一些页面是在 /subview/id1/id2.html 页面的。直接用oldLemmaId拼接 url 的话可能会有问题。
  • 有些城市(还是小城市。。。比如我的家乡),美食条目下根本不是美食。。。于是我不知道怎么办了😢

发表评论

电子邮件地址不会被公开。 必填项已用*标注