爬取靜態網站信息公司名稱以及電話

爬蟲需求:

需要爬取的網站 目標網站
爬取內容:需要爬取網站的公司名稱以及電話

公司名稱在列表頁
在這裏插入圖片描述聯繫方式在詳情頁
在這裏插入圖片描述

該網站有6000多條信息

在這裏插入圖片描述
1.考慮到網站信息太多,不能使用簡單的爬蟲請求頁面,需要考慮到單個ip無法滿足要求,網站訪問次數過多,會被網站反爬機制封ip
2.單個程序請求頁面,還要解析,單線程太慢

爬蟲思路解析

事先導入需要用的模塊

import random
import requests
from lxml import etree
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import time
1.封裝函數獲取網站所有頁碼
def get_pageurl(start, page_len, url):
    """
    :param start: 起止頁碼
    :param page_len: 頁碼個數
    :param url: 網站模板url
    :return: 
    """
    print('****************開始獲取取頁面URL****************')
    i = start
    j = 0
    url_list = []
    while j <= page_len:
    #網站頁碼規律 模板url http://shop.jc001.cn/r1-231/?p=
    # j爲頁碼數   url_full= 'http://shop.jc001.cn/r1-231/?p=' +頁碼數
        url_full = url + str(i)
        url_list.append(url_full)
        i += 1
        j += 1
    else:
        print('****************已爬取頁面URL****************')
        return url_list

2.通過獲取頁面的url去解析獲取每一個詳情頁的url

在這裏插入圖片描述

def get_allurls(url_list):
    print('****************開始爬取商家頁面URL****************')
    # 集合用來存儲不重複的所有詳情頁的url
    all_urls = set()
    count = 0
    for page_url in url_list:
        page_text = requests.get(url=page_url, headers=header,
                                 proxies={"http": random.choice(proxy_ip)}).text
        tree = etree.HTML(page_text)
        #解析每個頁面所包含的詳情頁的url
        a_list = tree.xpath('/html/body/div[8]/div[2]/div[2]/table/tbody/tr/td[1]/a/@href')
        for a in a_list:
            # a = "http:" + a
            all_urls.add(a)
            count += 1
    print('****************已爬取 %s 家商家頁面URL****************' % count)
    return all_urls
3.網站詳情頁請求以及解析

首先網站詳情頁6000多張 ,不可能網站一張張的去請求,這樣花費時間非常多,而且由於ip的訪問頻率限制,在請求的時候還需要設置請求間隔,以防單個ip請求速度過快導致ip被封,所以這裏需要用到多線程

3.1詳情頁請求函數

這裏注意一點,一定要使用異常模塊,想一想發生異常就要拋出一面紅看着就難受,所以這裏使用異常模塊,單個線程執行速度很快
time.sleep(0.5) random.choice(proxy_ip) 都是是爲了防止單個ip每秒內訪問服務器次數太多導致ip不可用。

def get_page(detail_url):
    time.sleep(0.5)
    try:
        response = requests.get(detail_url, headers=header, proxies={"http": random.choice(proxy_ip)}, timeout=5).text
    except Exception as e:
        response = ' '
    return {'url': detail_url, 'text': response}
3.2詳情頁解析函數(解析需要內容,並存儲)
def parase_page(res):
    # parse_page拿到的是一個future對象obj,需要用obj.result()拿到結果
    res = res.result()
    page_text = res.get('text')
    try:
        if page_text:
            tree = etree.HTML(page_text)
            name = tree.xpath('/html/body/div[2]/div[1]/div[1]/div/h3/a/text()')[0]
            num = tree.xpath('//div[@class="cnt line"]/table//tr[3]/td//text()')[0].strip('\xa0')
            with open('xiaogan.txt', 'a', encoding='utf-8') as f:
                f.write('%s|%s\n' % (name, num))
    except Exception as e:
        print(e)
3.3詳情頁解析總函數
def get_information(all_urls):
    print('****************開始爬取所有公司名稱電話****************')
    #線性池  15個線程同時執行
    p = ThreadPoolExecutor(15)
    for detail_url in all_urls:
    #add_done_callback(parase_page) 回調函數 執行完請求就回調解析模塊
        p.submit(get_page,detail_url).add_done_callback(parase_page)
UA僞裝以及代理IP

代理ip是在快代理上購買的私密ip

#UA僞裝
header = {
    "user-agent": "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
    'Connection': 'close',
    "Accept-Encoding": "Gzip",
}
#代理ip
#proxy_ip是一個包含30個代理ip的列表
api_url = "http://dps.kdlapi.com/api/getdps/?orderid=958623468831485&num=30&pt=1&format=json&sep=1"
proxy_ip = requests.get(api_url).json()['data']['proxy_list']

調用函數開始執行

url = "http://shop.jc001.cn/r1-239/?p="
url_list = get_pageurl(1,49, url)
all_urls = get_allurls(url_list)
print(all_urls)
get_information(all_urls)
最終結果

上面程序是運行一次可以爬取1000條資料,運行速度也很快,15線程同時運行
在這裏插入圖片描述
在這裏插入圖片描述
從代理ip網站後臺可以看到程序的響應數很高

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章