Python爬虫--真实世界的网页解析

2016-05-27  本文已影响0人  LineWay

用Requests + BeautifulSoup 爬取Tripadvistor

爬取一个网页需要两步:
1.服务器与本地的接交换机制
2.解析真实网页的方法

1.服务器与本地的交换机制

浏览网页的过程是通过浏览器向网站所在的服务器发送一个Request,同时服务器回应一个Response,这就是一个简单的HTTP协议
每一个Request请求包括很多种方法,目前(HTTP2.0)的方法有:getpostheadputoptionsconnecttracedelete,这八种方法。 GET和POST是最常用的两种方法。
爬虫抓取一个网页,实质上就是模拟这两种方法。

GET/page_one.html HTTP/1.1 Host:www.sample.com
以上是一个简单的get方法发送的请求方式,可以看出请求得到的信息包括页面的内容,协议的版本信息,以及网页的主域名。

一个正常打开的页面,返回的状态码应该是200,无法打开的页面一般返回403或者404

2.爬取Tripadvisor页面信息

爬取页面信息的步骤:
1.导入所需要的库
2.使用requests请求要爬取的网页
3.解析网页
4.描述要爬取的元素位置

#_*_ coding:utf-8 _*_


from bs4 import BeautifulSoup
import requests
import time


# part1
'''
url = 'http://www.tripadvisor.cn/Attractions-g60763-Activities-New_York_City_New_York.html'
wb_data = requests.get(url)
soup = BeautifulSoup(wb_data.text, 'lxml')
# 1.描述要爬取元素的位置
# Copy一下title的selector,测试一下结果
# titles = soup.select('#ATTR_ENTRY_105127 > div.property_title > a')
# print titles
# 打开原网页,查找title的父标签样式,发现在每一个<div class="property_title">下面的<a>标签中的内容就是title
# 那么更新一下titte的解析语句
titles = soup.select('div.property_title > a[target="_blank"]')

# 2.筛选所需要的元素
# 页面中存在的图片不一定全是所需要的,可以根据图片的属性(大小)对图片进行筛选
imgs = soup.select('img[width="160"]')

# 对其他的元素进行筛选
# tags一般是多对一的关系,所以在tags的父类标签进行筛选
cates = soup.select('div.p13n_reasoning_v2')

# 3.整理并筛选所需信息

for title, img, cate in zip(titles, imgs, cates):
    data = {
        'title': title.get_text(),
        'img': img.get('src'),
        'cate':list(cate.stripped_strings)
    }
    print data,'\n*************************************\n'
# 运行上述代码后发现,爬取的图片链接是一样的,也就意味着图片信息没有爬取下来
# 这是由于站点的反爬虫机制造成的,站点的图片加载是通过JavaScript控制的,暂时先不用管这些

# 4.使爬虫为登录站点的状态,构造向服务器提交的参数:headers
# 重新完成一个爬虫代码
'''

# part2
'''
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36',
    'Cookie':'__utma=55896302.1244431692.1455603774.1455603774.1455603774.1; __utmc=55896302; =',

}
url_saves = 'http://www.tripadvisor.cn/Saves#207971'
wb_data = requests.get(url_saves, headers=headers)
soup = BeautifulSoup(wb_data.text, 'lxml')

titles = soup.select('a.location-name')
imgs = soup.select('img.photo_image')
metas = soup.select('span.format_address')

for title, img, meta in zip(titles, imgs, metas):
    data = {
        'title':title.get_text(),
        'img':img.get('src'),
        'meta':list(meta.stripped_strings),
    }
    print data

'''


# 构造函数

url_saves = 'http://www.tripadvisor.cn/Saves#207971'
url = 'http://www.tripadvisor.cn/Attractions-g60763-Activities-New_York_City_New_York.html'
# 连续爬取30页的网页信息,发现每一页的区别在于 oa30 这个参数上,每一页的站点在这个数值的基础上增加30
# 所以可以用以下的格式进行爬取
urls = ['http://www.tripadvisor.cn/Attractions-g60763-Activities-oa{}-New_York_City_New_York.html#ATTRACTION_LIST'.format(str(i)) for i in range(30,930,30)]
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36',
    'Cookie':'__utma=55896302.1244431692.1455603774.1455603774.1455603774.1; __utmc=55896302; =',
}

def get_attractions(url, data=None):
    wb_data   = requests.get(url)
    time.sleep(4)
    soup      = BeautifulSoup(wb_data.text, 'lxml')
    titles    = soup.select('div.property_title > a[target="_blank"]')
    imgs      = soup.select('img[width="160"]')
    cates     = soup.select('div.p13n_reasoning_v2')
    for title, img, cate in zip(titles, imgs, cates):
        data = {
            'title':title.get_text(),
            'img': img.get('src'),
            'cate':list(cate.stripped_strings),
        }
        print data,'\n','*'*50,'\n'


def get_favs(url, data=None):
    wb_data = requests.get(url, headers=headers)
    soup    = BeautifulSoup(wb_data.text, 'lxml')
    titles  = soup.select('a.location-name')
    imgs    = soup.select('img.photo_image')
    metas   = soup.select('span.format_address')

    if data == None:
        for title, img, meta in zip(titles, imgs, metas):
            data = {
                'title':title.get_text(),
                'img':img.get('src'),
                'meta':list(meta.stripped_strings),
            }
            print data,'\n','*'*50,'\n'

for single_url in urls:
    get_attractions(single_url)


# 6.爬取多连续页的资料


代码演示了简单的爬虫,带Cookie的爬虫,以及连续爬取多个页面的爬虫。

为了应对站点的反爬虫机制,也可以利用模拟手机端登录的方式进行站点的爬取:

# 手机端抓取网页信息
from bs4 import BeautifulSoup
import requests


headers = {
    'User-Agent':'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
}

url = 'http://www.tripadvisor.cn/Attractions-g60763-Activities-oa30-New_York_City_New_York.html'
mb_data = requests.get(url, headers=headers)
soup = BeautifulSoup(mb_data.text, 'lxml')
imgs = soup.select('div.thumb.thumbLLR.soThumb > img')
for i in imgs:
    print i.get('src')


从代码中可以看出,模拟手机端的爬虫与一般的爬虫非常的相似,区别在于headers中的User-Agent是不一样的,这个也是非常简单的,Chrome浏览器可以通过很简单的方式进行手机端登录站点的模拟。具体实现可以在网上查找一下。

上一篇下一篇

猜你喜欢

热点阅读