【爬虫学习5】使用BeautifulSoup改进对知乎的爬取

来源:互联网 发布:如何制作mac os启动盘 编辑:程序博客网 时间:2024/06/05 02:14

在上一篇文章“使用selenium爬取知乎timeline“时,碰到一个问题:
知乎的timeline中得news有三类:
第一类
第二类
第三类

这三类都是分别包含在

<div class='Card TopstoryItem TopstoryItem--experimentExpand TopstoryItem--experimentButton'>...</div>

这样一个card里面,但是div内部具体实现不同。

直观地说
第一类是赞同、评论
第二类是发表文章
第三类是关注问题
这三类在div中包含的元素、元素的class、可获取的信息上都有区别
如果用正则表达式进行查找,很麻烦。
所以,用BeautifulSoup进行了一些尝试。


依然还是通过官方文档学习的beautifulsoup,有中文很方便。

代码如下:

from bs4 import BeautifulSoupfrom bs4 import NavigableStringfrom bs4 import Tagdef get_data(card):    datlis = ['name', 'fuc', 'title', 'author']    name = card.find('a', class_='UserLink-link', attrs = {'data-za-detail-view-element_name':'User'}).string    datlis[0] = name    gefuc = card.find_all('span', class_='Feed-meta-item')[-1].previous_sibling    #gefuc.strings的类型是generator 需要list    if isinstance(gefuc, Tag):        fuc = list(gefuc.strings)[-1]        datlis[1] = fuc    #这里根据card的类型进行区别对待    type1 = card.find('div', class_='QuestionItem-title')    type2 = card.find('div', itemprop='zhihu:question')    if type1:        title = type1.find('a').string        datlis[2] = title    elif type2:        title = type2.find('a').string        author = card.find('div', class_='AuthorInfo-content').find('div', class_='AuthorInfo-head').find('a')        datlis[2] = title        if isinstance(author,Tag):            datlis[3] = author.string    elif datlis[1] == '发表了文章':        title = card.find('h2', class_='ContentItem-title').find('a').string        author = name        datlis[2] = title        datlis[3] = author    return datlis#html为driver.get获取到的网页源码def get_datas(html):    soup = BeautifulSoup(html, 'lxml')    cards = soup.find_all('div', class_='Card TopstoryItem TopstoryItem--experimentExpand TopstoryItem--experimentButton')    for card in cards:        datlis = get_data(card)        yield {            'name' : datlis[0],            'fuc' : datlis[1],            'title' : datlis[2],            'author' : datlis[3]        }

在实现中碰到几个雷,在此做记录:
1. .strings是generator类型,需要list化来获取全部值。
2. .string获得的字符串是NavigableString类型,要操作先unicode(tag.string)
3. 要注意find到的对象的类型,通过对类型的判断可以省事很多
4. 对于包含-data字段的id或者class 要使用attrs={‘name’:’value}来筛选
5. 用习惯了dict后要记住list不能通过list[num]=value来加长list,而需要用append

本文代码还是见于我的Git
useBS4是源码
result2是结果
源码中使用的是之前爬取存在html.txt中的内容

阅读全文
0 0
原创粉丝点击