大数据 爬虫Python AI Sql

爬虫入门,看这一篇就够了

2019-01-08  本文已影响3人  Python从放弃到真香

目标读者:已经配置好Python环境,熟悉或了解Python基本语法,没有接触过爬虫的新手

本文旨在科普,用最简单明了的语言引导初学者接触爬虫,不求严谨。看到不懂的或者不想懂的专有名词不要纠结,只要代码没问题就继续下去,等爬取成功了再回头抠细节。

我将以虎扑火箭专区为例,爬取火区前一百页的标题。
(实在不喜欢火箭的可以用其它球队哈)

最先要说明的是,Python爬虫非常简单!(当然是指入门)

好了,直入主题吧!

导入三个模块

requests 用来发送请求(发送了请求,服务器才会响应你,你的浏览器才有内容显示)
pyquery 用来解析页面
fake_useragent 用来伪造请求头(相当于身份证)

import requestsfrom pyquery import PyQuery as pqfrom fake_useragent import UserAgent 

第一步 爬取

火箭专区地址:https://bbs.hupu.com/rockets
我们直接用requests发送get请求

url = 'https://bbs.hupu.com/rockets'r = requests.get(url)print(r)

这个r就是HTTP状态码,我们最常见的404也是状态码


1.png
print(r.text)
3.png

爬取页面就搞定了,不过出来的都是源码,我们要筛选出想要的信息

第二步 解析

要解析页面,必须先要了解一下页面的结构,我们先去火箭专区,然后右键第一个标题,检查(以chrome浏览器为例,360浏览器好像是审查元素)

image

Elements面板下展示的内容,就是网页的DOM节点和CSS样式,简单说就是网页的结构和内容,按小三角可以折叠和展开,鼠标放在代码上面,左边会高亮对应的内容,双击代码可以直接编辑。

image

<li>...</li> 这样的叫做标签
class="for-list" 这样带等号的叫做属性,有点像python的字典,等号左边是属性名,右边是属性值
class属性是非常常用的属性,也叫做类名

经过观察,我们会发现每个帖子信息都在li标签里面
而标题内容都在class属性为truetit的a标签里面

image.gif

下面简单粗暴地说下pyquery的语法(细讲的话要另起一文了)

标签直接写,
class属性前面加个点,
id属性前面加个#
空格表示嵌套关系(也就是子孙节点)
(结合下面代码理解)

#初始化,先让pyquery认识它,才能解析它doc = pq(r.text)#class属性为for-list的ul标签 下面的li标签#因为我们要分别取出每个li标签的内容,所以要加上items方法方便遍历info = doc('ul.for-list li').items()##对每个li标签,提取它嵌套的class属性为truetit的a标签的内容#获取文本用text方法for i in info:        title = i('a.truetit').text()        print(title)
image

成功了!
既然成功爬取了第一页,我们就试试爬前十页

要有网址才能爬取,所以我们先要解决网址的问题,常规思路是提取网站下一页的链接,但是虎扑的下一页其实是javascript渲染的。而我们用requests直接发送get请求得到的是未经渲染的原始信息。js渲染这种高级的东西我们目前无法解决,但我们通过点击下一页网址可以发现

似乎横杠后面的数字就是页数
我们试试-1,-10能不能转到第一页和第十页,结果是能的
所以我们就通过这个取巧的方法得到了前十页的网址
把我们之前的代码封装成函数

def get_title(n):    url = f'https://bbs.hupu.com/rockets-{n}'    r = requests.get(url)    doc = pq(r.text)    info = doc('ul.for-list li').items()    for i in info:            title = i('a.truetit').text()            print(title)

然后在1-10遍历一下

for i in range(11):    get_title(i)

十页标题就哗哗哗地爬出来了

但我们的目标是要爬100页的
照葫芦画瓢把range(11)改成range(101)不就可以了?

*for i in range(11):    get_title(i)

事实证明是不行的,出来的还是前十页的标题,那问题出在哪呢?
之前我们得到结论,横杠后面的就是页数,难道第十页之后网址变了?
于是我们打开浏览器,试着打开https://bbs.hupu.com/rockets-20
发现浏览器跳转到了登录界面,也就是说不登录是看不到10页以后的内容的

所以我们就要涉及到一个爬虫的基础知识了:headers(头部信息)
打开https://bbs.hupu.com/rockets-10
右键检查,进入network面板,这里记录了从发起网页页面请求后,分析HTTP请求后得到的各个请求资源信息
找到rockets-10,右边的headers面板记录了头部信息

image

一般来说,构建headers的时候,user-agent是必要的,相当于你的身份信息,告诉服务器你是谁
所以我们之前的爬虫里我们的身份是什么呢

#返回请求头信息print(r.request.headers)
image

这就相当于告诉服务器,我是python的requests模块,我来找你了,大多数网站看到“非正常浏览器“的身份都不会返回数据给你的,所以我们要假装成是正常浏览器

我们在刚刚的headers面板里可以看到自己的user-agent的信息,可以复制下来,requests请求的时候加上个参数headers,

headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}url = 'https://bbs.hupu.com/rockets-10'r = requests.get(url,headers=headers)

但是复制粘贴还是略麻烦,我们可以用fake_useragent来伪造个user-agent

from fake_useragent import UserAgentua = UserAgent()print(ua.random)
image

当然,这样我们还是无法得到第十一页的标题,因为我们在浏览器上输入第十一页的网址的时候,就弹出登录界面,用浏览器访问就相当于是正常浏览器身份了,所以不是user-agent的问题

难道每次我们都要手动登录才能爬吗?有没有方便点的方法?这种情况我们就要用上cookie了
首先我们要老老实实地手动登陆一次,这是避免不了的,然后打开https://bbs.hupu.com/rockets-10,右键检查,找到rockets-10的请求头信息,找到cookie,添加到headers里

image
ua = UserAgent()headers = {'user-agent':ua.random,'cookie':'把你的cookie粘贴过来'}url = f'https://bbs.hupu.com/rockets-{n}'r = requests.get(url,headers=headers)

添加了cookie,尝试一下

for i in range(101):    get_title(i)
image

下课!
公众号回复 【标题】 获取源码


v2-cc226c514c29bb8a618d57df23086891_hd.jpg
上一篇下一篇

猜你喜欢

热点阅读