【Day 11】- 还在 PTT 点击已满 18 岁? 带上 cookies 吧!(实战 PTT 爬虫 1/3)

前情提要

前一篇文章带大家看了网路爬虫的种类,下次看到类似的名词时能想到那一类的爬虫的特性。

开始之前

本篇将带各位实作爬取 PTT 的爬虫,在开始之前请各位准备好虚拟环境,各位记得将 pipenv --venv 放入 Vscode Settings,不知道如何设定可以回去看这篇 【Day 02】- 网路爬虫环境设定(Python、pipenv、Vscode)

这次爬取的网站是 PTT 八卦版 https://www.ptt.cc/bbs/Gossiping/index.html,会使用到 requestsbeautifulSoup

预期效果

可以绕过已满 18 岁的确认。

能够爬取当前页面的所有文章。

实作

首先先引入会用到的函式库,并将目标网址存於 url。

import requests
from bs4 import BeautifulSoup
url = 'https://www.ptt.cc/bbs/Gossiping/index.html'

直接向目标网址发一个 GET 之後看看回应物件的 text,发现并不是我们要的文章内容,而是一个确认是否 18 岁的页面。我们能用 google 直接浏览该页面也会发现需要点击已满 18 随才能进入网站内容。

resp = requests.get(url)
print(resp.text)

'''已将部分不必要内容删除
<!DOCTYPE html>
<html>
        <head>
                <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>批踢踢实业坊</title>
        </head>
    <body>
<div class="bbs-screen bbs-content">
    <div class="over18-notice">
        <p>本网站已依网站内容分级规定处理</p>
        <p>警告︰您即将进入之看板内容需满十八岁 
方可浏览。</p>
        <p>若您尚未年满十八岁,请点选离开。若您 
已满十八岁,亦不可将本区之内容派发、传阅、出售、
出租、交给或借予年龄未满18岁的人士浏览,或将本网
站内容向该人士出示、播放或放映。</p>
    </div>
</div>
<div class="bbs-screen bbs-content center clear">
    <form action="/ask/over18" method="post">   
        <input type="hidden" name="from" value="/bbs/Gossiping/index.html">
        <div class="over18-button-container">   
            <button class="btn-big" type="submit" name="yes" value="yes">我同意,我已年满十八岁<br><small>进入</small></button>
        </div>
        <div class="over18-button-container">   
            <button class="btn-big" type="submit" name="no" value="no">未满十八岁或不同意本条款<br><small>离开</small></button>
        </div>
    </form>
</div>
    </body>
</html>
'''

既然透过点击已满 18 岁可以成功进入八卦版,以及下次再进入网站不必再次点击,我们能直觉的联想到应该是用了 cookies 这项技术。

我们能用 https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm 来检视点击已满 18 岁後,该网域下的 cookies。

发现有个 cookies 名为 over18 数值为 1,要确认是否为这个 cookies 可以将其删除後再重新整理,会发现需要再次点击已满 18 岁。

了解到是 over18 这个 cookies 来纪录是否点击过已满 18 岁,我们能将这个 cookies 当作 requests.get 的参数一同传入。

将上方的程序加上了 cookies 传入。 於是可以正确取得文章内容了。

cookies = {
    'over18': '1'
}
resp = requests.get(url, cookies=cookies)
print(resp.text)

''' 已将部分不必要内容删除
<!DOCTYPE html>
<html>
    <body>
<a href="/bbs/Gossiping/M.1632305989.A.5E0.html">[协寻] 橘猫咪噜快点回家!(大安区)</a>
</div>
<div class="meta">
        <div class="author">k020231310</div>      
        <div class="article-menu">
                <div class="trigger">&#x22ef;</div>
                <div class="dropdown">
                        <div class="item"><a href="/bbs/Gossiping/search?q=thread%3A%5B%E5%8D%94%E5%B0%8B%5D&#43;%E6%A9%98%E8%B2%93%E5%92%AA%E5%9A%95%E5%BF%AB%E9%BB%9E%E5%9B%9E%E5%AE%B6%EF%BC%81%EF%BC%88%E5%A4%A7%E5%AE%89%E5%8D%80%EF%BC%89">搜寻同标题文章</a></div>       
                        <div class="item"><a href="/bbs/Gossiping/search?q=author%3Ak020231310">搜寻看板内 k020231310 的文章
</a></div>
                </div>
        </div>
        <div class="date"> 9/22</div>
        <div class="mark"></div>
    </body>
</html>
'''

有了包含文章内容的资料後,要用 BeautifulSoup 进行资料清洗,将我们要的内容清理出来。

可以用开发工具的选取功能选取文章,发现文章的元素都放在 class 为 r-ent 的 下面。

可以看到该 div 下面确实包含该文章的资讯。

我们能先爬取文章内容、文章连结及作者,这边用到了 BeautifulSoup 的基本操作,还不了解的读者能到 {Day 10} 看欧。

import requests
from bs4 import BeautifulSoup
url = 'https://www.ptt.cc/bbs/Gossiping/index.html'
cookies = {
    'over18': '1'
}
resp = requests.get(url, cookies=cookies)
soup = BeautifulSoup(resp.text, 'html5lib')
arts = soup.find_all('div', class_='r-ent')
for art in arts:
    title = art.find('div', class_='title').getText().strip()
    link = 'https://www.ptt.cc' + \
        art.find('div', class_='title').a['href'].strip()
    author = art.find('div', class_='author').getText().strip()
    print(f'title: {title}\nlink: {link}\nauthor: {author}')

'''
title: [问卦] 恒大要爆了没?经济要崩了没?鲁蛇要怎翻身
link: https://www.ptt.cc/bbs/Gossiping/M.1632408620.A.966.html
author: com2
title: [问卦] 玉山银行是不是5倍券的最大赢家
link: https://www.ptt.cc/bbs/Gossiping/M.1632408638.A.4A5.html
author: nnnn7615
title: Re: [新闻] 6成7台男月薪没5万不敢教女友 北部女:
link: https://www.ptt.cc/bbs/Gossiping/M.1632408645.A.5EB.html
author: bandwandbenz
title: [问卦] 回转寿司的回转484很多余?
link: https://www.ptt.cc/bbs/Gossiping/M.1632408657.A.B69.html
author: wang111283
...
'''

结语

今天实作了 Requests 中携带 cookies ,让网路爬虫不会被 18 岁验证挡住。

明日内容

明天将继续 PTT 爬虫,目前只会爬取当前文章,其实只要能爬取下一页网址,之後再向下一页发 GET,便可达到持续爬取。

补充资料

PTT 八卦版 : https://www.ptt.cc/bbs/Gossiping/index.html


<<:  30天学会 Python: Day 10-读进来!写出去!

>>:  【Day 26】JavaScript AJAX - XMLHttpRequest

Day 18 - Tally String Times with Reduce

前言 JS 30 是由加拿大的全端工程师 Wes Bos 免费提供的 JavaScript 简单应用...

设定档格式INI + Service的管理工具Systemd简介

INI INI, 全名是Initialization File 早期用来当设定档用的一种文件格式. ...

Day 30: 遗漏的章节

「目前为止,所有建议无疑将帮助你设计出更好的软件,这些软件是由具有明确边界、职责、依赖关系受控的元...

开放最短路径优先 (OSPF)

-动态路由(来源:Wayne Hickey) OSPF 可以作为路由器的一个组成部分运行;它还可以...

JavaScript 之旅 (28):Numeric Separators

本篇介绍 ES2021 (ES12) 提供的 Numeric Separators。 过去的 Nu...