zoukankan      html  css  js  c++  java
  • 使用beautifulsoup与requests爬取数据

    1、安装需要的库

    bs4 beautifulSoup  requests lxml
    如果使用mongodb存取数据,安装一下pymongo插件

    2、常见问题

    1> lxml安装问题

    如果遇到lxml无法安装问题,参考知乎上的答案:

    首先,安装wheel,命令行运行:pip install wheel
    其次,在这里下载对应的.whl文件,注意别改文件名!http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml
    Ctrl + F,输入lxml,找到下面这段Lxml,
    Lxml, a binding for the libxml2 and libxslt libraries.
    lxml‑3.7.1‑cp27‑cp27m‑win32.whl

    lxml‑3.7.1‑cp27‑cp27m‑win_amd64.whl

    lxml‑3.7.1‑cp34‑cp34m‑win32.whl

    lxml‑3.7.1‑cp34‑cp34m‑win_amd64.whl

    lxml‑3.7.1‑cp35‑cp35m‑win32.whl

    lxml‑3.7.1‑cp35‑cp35m‑win_amd64.whl

    lxml‑3.7.1‑cp36‑cp36m‑win32.whl

    lxml‑3.7.1‑cp36‑cp36m‑win_amd64.whl
    cp后面是Python的版本号,27表示2.7,根据你的Python版本选择下载。
    之后, 进入.whl所在的文件夹,执行命令即可完成安装pip install 带后缀的完整文件名

    2> pip问题
    如果提示 'pip' 不是内部或外部命令,也不是可运行的程序。

    多是因为环境变量没有设置好。需要设置两个,一些常用的命令在Scripts文件夹下面

    以下两个改为自己计算机的路径

    C:FilesPythonPython36
    C:FilesPythonPython36Scripts

    3、mongodb

    如何安装mongodb参见https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/

    服务启动与停止

    sudo service mongod start
    sudo service mongod stop
    sudo service mongod restart

    配置文件位于 /etc/mongod.conf,默认端口 27017 ,修改可以在配置文件中修改

    # network interfaces
    net:
      port: 27017
    #  bindIp: 127.0.0.1

    此外,默认绑定了ip地址127.0.0.1,需要将此句注释掉,否则远程无法访问

    4、参考代码

    import requests
    from bs4 import BeautifulSoup
    import time
    import pymongo
    import random
    from multiprocessing import Pool
    # 导入多个对象或者函数用逗号分开
    # from test_parsing import get_items,url_list
    
    # mongodb客户端
    client = pymongo.MongoClient('192.168.1.101',27017)
    # 数据库
    test = client['testdata']
    # 各种表
    tb = test['testtable']
    mb= test['itemtable']
    detail= test['detailtable']
    
    headers  = {
    User-Agent:
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
        'Connection':'keep-alive'
    }
    
    
    proxy_list = [
        'http://118.79.27.123:8081',
        'http://113.108.253.195:9797',
        ]
    
    # 随机获取代理ip
    proxy_ip = random.choice(proxy_list) 
    proxies = {'http': proxy_ip}
    
    # 简单用例
    def get_pages_within(pagenums):
        for page_num in range(1,pagenums+1):
            # 请求
            wb_data = requests.get('http://urldata/test/pn{}/'.format(page_num))
            # 包装一个对象
            soup = BeautifulSoup(wb_data.text,'lxml')
            # 使用select方法,参数为样式选择器,div.price_li > span 标识逐层级关系,div.price_li span 只是简单的包含关系        
            numbers = soup.select('div.number')
            prices = soup.select('span.price')
            
            links = soup.select('a.t')
    
            for number, price, link in zip(numbers,prices,links):             
                if int(price.get_text()) > 500:
                    print(number,price)
                data = {
                    'title':number.get_text(),
                    'price':price.get_text(),
                    'link' :link.get('href')
                }
                tb.insert_one(data)
            print('finished')
    
    # 复杂点的
    def get_links_from(source, pages, flag='c'):
        list_view = '{}{}{}/'.format(source, str(flag), str(pages))
        # 带参数
        wb_data = requests.get(list_view,headers=headers,proxies=proxies)
        soup = BeautifulSoup(wb_data.text, 'lxml')
        if soup.find('ul', 'pageLink'):
            for link in soup.select('.fenlei dt a'):
                item_link = link.get('href')
                mb.insert_one({'url': item_link})
                print(item_link)
                
        else:
            pass
    
    
    def get_detail_from(url,data=None):
        wb_data = requests.get(url,headers=headers)
        time.sleep(1)
        # flag = 'flagnumber' in soup.find('script', type="text/javascript").get('src').split('/')
        # if flag: 
        if wb_data.status_code == 404:    
            pass
        else:
            soup = BeautifulSoup(wb_data.text, 'lxml')
            data = {
                'title':soup.title.text.strip(),
                'price':soup.select('div.price_li > span > i')[0].text.strip(),
                'time':soup.select('.pubtime')[0].text.strip().split('/')[0],
                'area':list(map(lambda x:x.text,soup.select('ul.area-infor > li > a'))),
                'cates':list(soup.select('div.cates > span > i')[0].stripped_strings),
                'url':url
            }       
            detail.insert_one(data)
    
    source_list = '''
    http://test.com/books/
    http://test.com/pictures/
    '''
    
    # 读取数据
    # $lt/$lte/$gt/$gte/$ne,依次等价于</<=/>/>=/!=。(l表示less g表示greater e表示equal n表示not  )
    for item in detail.find({'price': {'$lt': 100}}):
        print(item)
        
    for i in detail.find():
        if i['price'] >= 500:
            print(i)
    
    if __name__ == '__main__':
        # 使用多进程
        pool = Pool()
        # pool = Pool(processes=2)
        if source_list is not None:
            pool.map(get_links_from,source_list.split())
        
        pool.close()
        pool.join()

    一般使用谷歌浏览器对要爬取的元素进行检查,在这一方面,好用一些,右键,选择Copy selector,获取到例如:div.cates > span > i,作为select函数的参数即可。

     也可以自己写,在浏览器的检查元素页面上,ctrl + F 出现查找框,写入要使用的样式选择器,看看是否准确即可 。

    例子:div.price_li > span 标识逐层级关系,div.price_li span 只是简单的包含关系

     

     5、参考文档

    http://beautifulsoup.readthedocs.io/zh_CN/latest/

    http://www.python-requests.org/en/master/

  • 相关阅读:
    Java 简单算法--打印乘法口诀(只使用一次循环)
    Java简单算法--求100以内素数
    ubuntu 16.04 chrome flash player 过期
    java 网络API访问 web 站点
    java scoket (UDP通信模型)简易聊天室
    leetcode1105 Filling Bookcase Shelves
    leetcode1140 Stone Game II
    leetcode1186 Maximum Subarray Sum with One Deletion
    leetcode31 Next Permutation
    leetcode834 Sum of Distances in Tree
  • 原文地址:https://www.cnblogs.com/learn21cn/p/6243537.html
Copyright © 2011-2022 走看看