Я несколько дней учился писать краулер на питоне, давайте напишем небольшой краулер, чтобы проверить результаты обучения. Эта статья подходит для еды Xiaobai, всем хорошо провести время~
Совет: Эта статья предназначена только для обучения и общения, не используйте ее в незаконных целях! ! !
1. Веб-анализ
Чтобы сканировать информацию о вторичном жилье в Шицзячжуане с Shell.net, сначала откройте ссылку.https://sjz.ke.com/ershoufang/
.Без добавления фильтров всего было найдено 42 817 домов. Нажимаем на вторую страницу, после чего ссылка просмотра становитсяhttps://sjz.ke.com/ershoufang/pg2/
. Поэтому можно найти/pg{i}
, я - номер страницы. После того, как учитель физкультуры Латиаоцзюнь преподавал математику, я подсчитал, что на каждой странице 30 страниц, и можно выбрать максимум 100 страниц.Таким образом, вы можете просканировать до 3 000 наборов информации о свойствах, что все еще далеко от 40 000, указанных выше, поэтому попробуйте поместитьpg{i}
Если я искусственно изменил его, нажмите Enter, чтобы запросить его.
https://sjz.ke.com/ershoufang/pg200/
https://sjz.ke.com/ershoufang/pg300/
Обнаружено, что эти два запроса возвращают одни и те же данные информации о недвижимости. Это вся информация на странице 100, так что делайте выводы.通过贝壳网web端,查看某一条件下的房产信息,最多可以查看3000套
. Блин, можно купить максимум 3000 наборов.Очень неудобно иметь деньги и не иметь возможности их потратить~ Побег :)~~
Итак, мы добавляем некоторые условия, например, тот, у которого всего пять комнат, и тот, у которого 2 комнаты. запрос~обнаружил, что ссылка сталаhttps://sjz.ke.com/ershoufang/pg2mw1l2/
.mw1l2
Это дело надо фильтровать. Видя, что наборов всего 2399, Ок, полезем.
2. Засучите рукава и напишите код
Хотя воробей маленький и цельный, эта рептилия состоит из трех частей.爬取,解析,储存
.
Ползание
Сканировать и использоватьrequests
Библиотеки, чем встроенные библиотеки Pythonurllib
Гораздо проще в использовании.
import requests
def get_a_page(url):
result = requests.get(url)
print(result.text)
if __name__ == '__main__':
for i in range(1, 101):
get_a_page(f'https://sjz.ke.com/ershoufang/pg{i}mw1l2/')
Цикл for печатает возвращенные данные и не обнаруживает проблем. На самом деле, было бы хорошо, если бы я зациклился на 81. Ведь мы знаем, что наборов всего меньше 2400.
Разобрать
Разбор использованияpyquery
, эта библиотека похожа на Jquery в использовании. полный API,https://pythonhosted.org/pyquery/api.html
. Также есть библиотека разбора `bs4, попробуйте в следующий раз.
Найдите показания, как показаноul
внутри одногоdiv
Мы можем получить нужные нам данные.
import requests
from pyquery import PyQuery as pq
import json
def get_a_page(url):
result = requests.get(url)
doc = pq(result.text)
ul = doc('.sellListContent')
divs = ul.children('.clear .info.clear').items()
for div in divs:
count += 1
title = div.children('.title a').text()
place = div.children('.address .flood .positionInfo a').text()
msg = div.children('.address .houseInfo').text()
price = div.children('.address .priceInfo .totalPrice span').text()
per_meter = div.children('.address .priceInfo .unitPrice').attr('data-price')
dict = {
'title': title,
'place': place,
'msg': msg,
'price': price,
'per_meter': per_meter
}
print(str(count) + ':' + json.dumps(dict, ensure_ascii=False))
Код такой же, как указано выше, pyquerychildren
Способ состоит в том, чтобы найти подтег,find
Метод заключается в том, чтобы найти метку-потомка, здесь нам нужно только найти следующее поколение. затем пройтиtext
Найдите текст, содержащийся в этикетке.attr
состоит в том, чтобы получить содержимое атрибута, потому что этоper_meter
Его относительно просто получить из атрибута, а содержание на этикетке также включает «юань/квадратный метр».
хранить
На этот раз мы храним прямо вcsv
, похожий наexcel
формат файла. использованиеpandas
библиотека.
Полный код выглядит следующим образом:
import requests
from pyquery import PyQuery as pq
import json
import pandas as pd
columns = ['title', 'msg', 'price', 'per_meter']
# 爬取某网页
def get_a_page(url):
result = requests.get(url)
doc = pq(result.text)
ul = doc('.sellListContent')
divs = ul.children('.clear .info.clear').items()
count = 0
titles = []
places = []
msgs = []
prices = []
per_meters = []
for div in divs:
count += 1
title = div.children('.title a').text()
place = div.children('.address .flood .positionInfo a').text()
msg = div.children('.address .houseInfo').text()
price = div.children('.address .priceInfo .totalPrice span').text()
per_meter = div.children('.address .priceInfo .unitPrice').attr('data-price')
dict = {
'title': title,
'place': place,
'msg': msg,
'price': price,
'per_meter': per_meter
}
titles.append(title)
places.append(place)
msgs.append(msg)
prices.append(price)
per_meters.append(per_meter)
print(str(count) + ':' + json.dumps(dict, ensure_ascii=False))
datas={
'title': titles,
'place': places,
'msg': msgs,
'price': prices,
'per_meter': per_meters
}
df = pd.DataFrame(data=datas, columns=columns)
df.to_csv('sjz.csv', mode='a', index=False, header=False)
if __name__ == '__main__':
for i in range(1, 101):
get_a_page(f'https://sjz.ke.com/ershoufang/pg{i}mw1l2/')
мультипрогресс
потому чтоget_a_page
Функция должна запускаться 100 раз, что немного медленно, поэтому используйте несколько процессов, чтобы ускорить скорость. Пожалуйста, скопируйте эту часть кода напрямую.
Измените основную функцию на следующую
from multiprocessing.pool import Pool
if __name__ == '__main__':
pool = Pool(5)
group = ([f'https://sjz.ke.com/ershoufang/pg{x}mw1l2/' for x in range(1, 101)])
pool.map(get_a_page,group)
pool.close()
pool.join()
3. Конец
Обратите внимание на следующие эффекты:
Эффект в порядке. Некоторые люди скажут, почему бы не разделить информацию msg и хранить этажи, комнаты и залы, возраст здания и т. д. отдельно. В начале я так и сделал, и обнаружил, что элементы данных msg не требуются.Некоторые домовладельцы возраста здания, этажа и т. д. не заполнили их, поэтому они просто взяли их все.
Это конец первого сканера Латиао Цзюня. Хотя это просто, это все же немного удовлетворяет, когда это написано. В будущем я продолжу изучать поисковые роботы и буду вести блоги. Друзья, ставьте лайк и уходите~