7.2 动态网页的爬取技巧
7.2.1 链家经纪人页面分析
本节要爬取链家的经纪人数据,这次选择爬取链家网的移动页面,毕竟移动页面相对干净、简单。上一节已经提到,移动版的链家经纪人列表页面采用了动态加载的技术,也就是说在 URL 不变的情况下,向下拉滚动条,可以不断加载新的数据。如果爬虫只是简单地爬取经纪人列表页面的 URL,只能得到初次加载的有限数据,后面的经纪人信息是爬取不到的。我们知道,既然加载了新的数据,系统一定发出了请求,我们就要仔细的分析,系统到底向服务器发送了什么样的请求。分析出来后,可以尝试构造同样的请求,从而用代码爬取后续加载的内容。
用 Chrome 浏览器打开链家网北京移动端经纪人列表页面,打开 Chrome 浏览器的“检查”功能,在弹出的检查子页面中选择 Network 栏目,这时 Network 栏目下的请求内容是空的,如图 7-3 所示。
图 7-3 检查子页面中的 Network 栏目
现在把网页右侧的滚动条拉到底,让网页加载一些新的数据进来,Network 里出现了很多请求的信息,如图 7-4 所示。
图 7-4 Network 栏目记录的请求信息
这些请求信息大部分都是以 jpg 结束的图片请求,但是也有很特别的请求 URL,如 https://m.lianjia.com/bj/jingjiren/?page_size=15&_t=1&offset=15。这一条请求很特别,它包含 page_size 和 offset 这样的关键字,值得关注。现在继续拉滚动条到底,再次加载新的数据,看看 Network 栏目中有没有新的类似的 URL 产生,结果如图 7-5 所示。
图 7-5 Network 栏目记录的新请求信息
除了下载图片的请求,这里出现了 https://m.lianjia.com/bj/jingjiren/?page_size=15&_t=1&offset=30 这样的请求。可以看到它的 offset 发生了变化,由 15 变成了 30。再向下拉动一次,又能发现新的请求 https://m.lianjia.com/bj/jingjiren/?page_size=15&_t=1&offset=45。
至此可以总结一个规律,那就是每次请求 offset 增加 15,可以把这几条请求用网页单独打开,会发现它们是不同的经纪人列表页面,这样就找到了网页在后端实际请求的 URL 和其变化的规律。下面就可以根据发现的规律构造请求 URL,然后爬取经纪人信息了。
7.2.2 链家经纪人爬虫实现
本节根据前面的分析,编写一个爬取链家经纪人数据的简单爬虫。为了简单演示,这里只爬取经纪人的姓名和负责区域这两项信息。首先导入需要的包,编写保存函数。
import requests import csv import time from lxml import etree def csv_writer(item): with open('lianji_jingjiren.csv', 'a', encoding='gbk', newline='') as csvfile: writer = csv.writer(csvfile) writer.writerow(item)
下面定义一个 spider 函数,负责下载经纪人列表页并解析。
def spider(list_url): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) \ AppleWebKit/537.36 (KHTML, like Gecko) \ Chrome/46.0.2490.80 Safari/537.36'} Response = requests.get(list_url, headers=headers) time.sleep(5) sel = etree.HTML(response.text) #构造信息提取器 #先爬取每一位经纪人的整体代码段 agent_list = sel.xpath('//li[@class="pictext flexbox box_center_v"]') for agent in agent_list: #循环解析出经纪人的信息 agent_name = agent.xpath('div[2]/div[1]/span[1]/a/text()')[0] agent_region = agent.xpath('div[2]/div[2]/span[1]/text()')[0] item = [agent_name, agent_region] print('正在爬取:', agent_name) csv_writer(item) #保存爬取的数据
在这里有一点再次提示读者,每一个经纪人代码段中的相对 XPath 路径可以参考 Chrome 浏览器中复制出来的 XPath。例如,从 Chrome 中复制某个经纪人代码段的 XPath 路径,然后再复制这个经纪人姓名的 XPath 路径,两条路径之间的不同之处就是姓名在经纪人代码段中的相对 XPath 路径。这样比我们自己编写 XPath 路径简单许多。
下面编写主程序,实现以下功能:在循环中构造经纪人网页的请求地址,交给 spider 函数处理。例如这次爬取 1500 个经纪人的信息,每页显示 15 个经纪人,就需要爬取 100 页。
if __name__ == '__main__': for i in range(1, 101): url = ( 'https://m.lianjia.com/bj/jingjiren/ + '?page_size = 15&_t=1&offset = ' + str(i*15)) spider(url)
这里根据加载新内容时 offset 的变化规律,用一个 for 循环,构造不同页面的 URL 请求,然后交给 spider 函数执行爬取功能。
以上就是处理 URL 不变类型动态页面的典型处理办法。读者在遇到类似 URL 不变、拉动滚动条或者单击某个按钮就能加载数据的情况时,一定要注意分析网站到底向服务器发送了什么样的请求,然后模仿这个请求,从而获得新的数据。
上面爬取链家移动网站的例子中,我们通过分析,发现了实际请求的 URL,然后在浏览器中直接打开这个 URL,显示的是正常的页面,但是很多时候,如爬取 36 氪的首页文章,如果按照本节的思路分析,会发现它也像链家网一样在发送请求,但是如果把请求的链接直接在浏览器中打开,会发现接收到的数据是 json 格式的。对于返回 json 数据的处理方法,第八章将在爬取拉勾网招聘职位的实例中演示。
在本节编写爬虫的过程中,最关键的是要发现网页向服务器发送的请求 URL,然后在爬虫中构造这个 URL。但是这种方法并不是万能的,有些动态网站的请求非常复杂,我们很难通过观察发现它的规律,如新浪微博,当登录后浏览的时候,通过 Chrome 浏览器的检查功能,会发现它请求的 URL 非常长而且难以发现其构造规律,这个时候就要用到下一节讲解的 Selenium 库了。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论